Kotlin學(xué)習(xí)筆記(8)- 擴展

系列文章全部為本人的學(xué)習(xí)筆記禁悠,若有任何不妥之處弃揽,隨時歡迎拍磚指正鼓择。如果你覺得我的文章對你有用三幻,歡迎關(guān)注我,我們一起學(xué)習(xí)進(jìn)步呐能!
Kotlin學(xué)習(xí)筆記(1)- 環(huán)境配置
Kotlin學(xué)習(xí)筆記(2)- 空安全
Kotlin學(xué)習(xí)筆記(3)- 語法
Kotlin學(xué)習(xí)筆記(4)- 流程控制
Kotlin學(xué)習(xí)筆記(5)- 類
Kotlin學(xué)習(xí)筆記(6)- 屬性
Kotlin學(xué)習(xí)筆記(7)- 接口
Kotlin學(xué)習(xí)筆記(8)- 擴展
Kotlin學(xué)習(xí)筆記(8)- 擴展(續(xù))
Kotlin學(xué)習(xí)筆記(9)- 數(shù)據(jù)類
Kotlin學(xué)習(xí)筆記(10)- 泛型
Kotlin學(xué)習(xí)筆記(11)- 內(nèi)部類和嵌套類
Kotlin學(xué)習(xí)筆記(12)- 委托
Kotlin學(xué)習(xí)筆記(13)- 函數(shù)式編程
Kotlin學(xué)習(xí)筆記(14)- lambda

今天要開始學(xué)習(xí)擴展(Extension)了念搬,擴展是kotlin中非常重要的一個特性,它能讓我們對一些已有的類進(jìn)行功能增加摆出、簡化朗徊,使他們更好的應(yīng)對我們的需求。這么說可能有點枯燥偎漫,我們先來看一個小栗子爷恳。

//  對Context的擴展,增加了toast方法象踊。為了更好的看到效果舌仍,我還加了一段log日志
fun Context.toast(msg : String){
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
    Log.d("text", "Toast msg : $msg")
}

// Activity類,由于所有Activity都是Context的子類通危,所以可以直接使用擴展的toast方法
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ......
        toast("hello, Extension")
    }
}

// 輸出
Toast msg : hello, Extension

怎么樣,有沒有一點小激動灌曙,反正我是有的菊碟。按照通常的做法,我們會寫一個ToastUtils工具類在刺,或者在BaseActivity中實現(xiàn)toast方法逆害,但是現(xiàn)在這些統(tǒng)統(tǒng)不需要了头镊,直接給Context增加擴展,這樣不論是Activity或者Service都可以直接調(diào)用魄幕,更簡潔相艇、更優(yōu)雅。接下來是我的學(xué)習(xí)進(jìn)程纯陨,希望也能對你有所幫助坛芽。

一、擴展方法(Extension Function)

擴展方法翼抠,顧名思義咙轩,就是對類的方法進(jìn)行擴展,寫法和定義方法類似阴颖,但是要聲明目標(biāo)類活喊,也就是對哪個類進(jìn)行擴展,kotlin中稱之為Top Level量愧。就比如上面的栗子钾菊。

fun Context.toast(msg : String){
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
    Log.d("text", "Toast msg : $msg")
}

其中,Context就是目標(biāo)類(Top Level)偎肃,我們把它放到方法名前煞烫,用點.表示從屬關(guān)系。在方法體中软棺,用關(guān)鍵字this對本體進(jìn)行調(diào)用红竭。和普通方法一樣,如果有返回值喘落,在方法后面跟上返回類型茵宪,我這里沒有返回值,所以直接省略了瘦棋。

還有一點很神奇的是稀火,我們可以允許目標(biāo)類接受null。不是說對null進(jìn)行擴展赌朋,而是可以設(shè)置目標(biāo)類為一個可以為空的對象凰狞。再舉一個栗子,也是我們很常用的功能:

fun Any?.string() : String = if(this == null) "null obj" else toString()

var a = 1
toast("hello, ${a.string()}")
var b : View? = null
toast("hello, ${b.string()}")

// 輸出
Toast msg : hello, 1
Toast msg : hello, null obj

在這里我們對Any進(jìn)行擴展沛慢,它在konlin中類似于java中的Object赡若,所有的類都繼承與它,我們給它擴展了一個string()方法团甲。還記得嗎逾冬,類型后面跟問號?表示可為空。在這里當(dāng)目標(biāo)為null時,我們返回了一個字符串身腻,看一下調(diào)用产还,再看一下輸出,完全和預(yù)想的一樣嘀趟。

kotlin中其實已經(jīng)默認(rèn)對toString方法進(jìn)行了處理脐区,如果是空,則會返回字符串null她按。這其實很多時候不符合我們的需求牛隅,我們可以自己擴展一下,將返回值改為空字符串就好尤溜。

fun Any?.string() : String = if(this == null) "" else toString()

二倔叼、擴展屬性(extension property)

擴展屬性和擴展方法類似,是對目標(biāo)類的屬性進(jìn)行擴展宫莱。擴展屬性也會有setget方法丈攒,并且要求實現(xiàn)這兩個方法,不然會提示編譯錯誤授霸。因為擴展并不是在目標(biāo)類上增加了這個屬性巡验,所以目標(biāo)類其實是不持有這個屬性的,我們通過getset對這個屬性進(jìn)行讀寫操作的時候也不能使用field指代屬性本體碘耳∠陨瑁可以使用this,依然表示的目標(biāo)類辛辨。

// 擴展了一個屬性paddingH
var View.panddingH : Int
    get() = (paddingLeft + paddingRight) / 2
    set(value) {
        setPadding(value, paddingTop, value, paddingBottom)
    }

// 設(shè)置值
text.panddingH = 100

在栗子中捕捂,我們首先給View擴展了一個屬性paddingH,并給屬性增加了setget方法斗搞,然后再activity中通過textview調(diào)用指攒。

三、靜態(tài)擴展

  1. kotlin中的靜態(tài)用關(guān)鍵字companion表示僻焚,而且它不是修飾屬性或方法允悦,而是定義一個方法塊,在方法塊中的所有方法和屬性都是靜態(tài)的虑啤,這樣就將靜態(tài)部分統(tǒng)一包裝了起來隙弛。靜態(tài)部分的訪問和java一致,直接使用類名+靜態(tài)屬性/方法名就可以

    // 定義靜態(tài)部分
    class Extension {
        companion object part{
            var name = "Extension"
        }
    }
    
    // 通過類名+屬性名直接調(diào)用
    toast("hello, ${Extension.name}")
    
    // 輸出
    Toast msg : hello, Extension
    

    上面栗子中狞山,companion object一起是修飾關(guān)鍵字全闷,part是方法塊的名稱。其中萍启,方法塊名稱part可以省略总珠,如果省略的話,默認(rèn)缺省名為Companion

  2. 靜態(tài)的擴展和普通的擴展類似,但是在目標(biāo)類要加上靜態(tài)方法塊的名稱姚淆,所以如果我們要對一個靜態(tài)部分?jǐn)U展,就要先知道靜態(tài)方法塊的名稱才行屡律。

    class Extension {
        companion object part{
            var name = "Extension"
        }
    }
    
    // part為靜態(tài)方法塊名稱
    fun Extension.part.upCase() : String{
        return name.toUpperCase()
    }
    
    // 調(diào)用一下
    toast("hello, ${Extension.name}")
    toast("hello, ${Extension.upCase()}")
    
    //輸出
    Toast msg : hello, Extension
    Toast msg : hello, EXTENSION
    

四腌逢、引用

在AS中,如果我們使用擴展方法和擴展屬性超埋,大部分情況下會自動提示導(dǎo)入import搏讶,但有時候如果沒有提示,就需要手動import一下了霍殴。擴展的import路徑為:包名+方法名/屬性名媒惕,比如我最先創(chuàng)建的擴展方法toast,其實文件全部是這樣的

package com.study.jcking.weatherkotlin.exec

import android.content.Context
import android.util.Log
import android.widget.Toast

/**
 * Created by Jcking on 2017/6/3.
 */
fun Context.toast(msg : String){
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
    Log.d("text", "Toast msg : $msg")
}

可見来庭,toast方法沒有在類內(nèi)部妒蔚,而是與包名同級,當(dāng)然這不是絕對月弛,只是習(xí)慣這樣寫肴盏,那我們引用的時候就這樣寫import

import com.study.jcking.weatherkotlin.exec.toast

五、最后

以上就是個人學(xué)習(xí)擴展的一些總結(jié)帽衙,東西不多菜皂,但是感覺是kotlin中很重要的一部分。他讓我們的代碼更簡潔厉萝,更優(yōu)雅恍飘,而且功能定位更準(zhǔn)確、更清晰谴垫。再有章母,就是感覺一大波util要下崗了~

最后拋出個問題罪帖,暫時還沒有搞明白但两,希望小伙伴們幫我解惑:如果我將擴展沒有放在包名同級,而是放在一個類的內(nèi)部羽嫡,在語法上是完全沒有問題的肢专,但是類外部調(diào)用卻好像不行了舞肆。請問是它失去了對外部的可見性,還是我的調(diào)用方式有問題博杖?歡迎討論指教椿胯,先行謝過!剃根!

更新:2017年6月4日
問題已經(jīng)找到資料了哩盲,確實是不行的,請看我下一篇筆記: Kotlin學(xué)習(xí)筆記(8)- 擴展(續(xù))

Extension類,包package com.study.jcking.weatherkotlin.exec

package com.study.jcking.weatherkotlin.exec

class Extension {
    companion object part{
        var name = "Extension"
    }

    fun Context.toast(msg : String){
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
        Log.d("text", "Toast msg : $msg")
    }
}

調(diào)用類廉油,包package com.study.jcking.weatherkotlin

package com.study.jcking.weatherkotlin

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        toast("hello, ${Extension.upCase()}")       // 這里toast報錯惠险,編譯錯誤,無法調(diào)用
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抒线,一起剝皮案震驚了整個濱河市班巩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嘶炭,老刑警劉巖抱慌,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異眨猎,居然都是意外死亡抑进,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門睡陪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寺渗,“玉大人,你說我怎么就攤上這事宝穗。” “怎么了逮矛?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵鸡号,是天一觀的道長鲸伴。 經(jīng)常有香客問我,道長只洒,這世上最難降的妖魔是什么许帐? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮毕谴,結(jié)果婚禮上成畦,老公的妹妹穿的比我還像新娘距芬。我一直安慰自己,他們只是感情好循帐,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布框仔。 她就那樣靜靜地躺著,像睡著了一般拄养。 火紅的嫁衣襯著肌膚如雪存和。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天衷旅,我揣著相機與錄音,去河邊找鬼纵朋。 笑死柿顶,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的操软。 我是一名探鬼主播嘁锯,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼聂薪!你這毒婦竟也來了家乘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤藏澳,失蹤者是張志新(化名)和其女友劉穎仁锯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翔悠,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡业崖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓄愁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片双炕。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖撮抓,靈堂內(nèi)的尸體忽然破棺而出妇斤,到底是詐尸還是另有隱情,我是刑警寧澤丹拯,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布站超,位于F島的核電站,受9級特大地震影響咽笼,放射性物質(zhì)發(fā)生泄漏顷编。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一剑刑、第九天 我趴在偏房一處隱蔽的房頂上張望媳纬。 院中可真熱鬧双肤,春花似錦、人聲如沸钮惠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽素挽。三九已至蔑赘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間预明,已是汗流浹背缩赛。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留撰糠,地道東北人酥馍。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像阅酪,于是被迫代替她去往敵國和親旨袒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容