
在Kotlin中沒有方法這個概念,轉(zhuǎn)而存在的是函數(shù)的概念。
函數(shù)的聲明
我們聲明一個函數(shù),使用fun關(guān)鍵字來修飾函數(shù)。
fun print(){
print("this is message");
}
fun print(str:String){
print("this is message $str");
}
fun print1(str:String = "hello"){
print("this is message $str");
}
fun printMessage() = print("this is kotlin");
fun printMsg():String = "this is kotlin";
我們可以看到這里我寫了五種函數(shù)的書寫方式。
第一種,是我們常用的方式,小括號里面沒有參數(shù),我們可以直接輸出print信息。
第二種,里面是有一個參數(shù)str,我們在使用的時候可以傳入一個參數(shù),之后用print打印出這個參數(shù)值。
第三種,kotlin可以在參數(shù)中設(shè)置一個默認(rèn)值,例如這里我將str設(shè)置了一個默認(rèn)值"hello",當(dāng)在使用這個函數(shù)print1的時候沒有傳入str這個參數(shù),那么輸出的時候?qū)⒉捎媚J(rèn)值來輸出。結(jié)果打印this is message hello。這是kotlin中特有的語法。
第四種,如果函數(shù)中只有一條語句,那么我們可以直接使用"="來將這一條語句直接賦值給這個printMessage()函數(shù)。
第五種,同理第四種情況,如果函數(shù)有返回值并且也只有一條語句,那么我們也同樣可以直接賦值操作。
函數(shù)的嵌套
我們來看下面這段代碼
fun function(){
var str:String = "hello";
fun getFunction(){
var msg:String = "world";
var account:Int = 100;
print("$str $msg");
if (account >= 100){
account--;
}
getFunction();
}
}
可以看到在function這個函數(shù)中嵌套了另外一個函數(shù)getFunction(),并且在getFunction()中使用到了外部函數(shù)Function的變量str。這個有點像Java中內(nèi)部類的概念。在Kotlin中允許函數(shù)內(nèi)再嵌套另外一個函數(shù),并且內(nèi)部的函數(shù)可以調(diào)用外部函數(shù)聲明的變量,并且函數(shù)自身還可以調(diào)用自身。這種寫法一般用于某些情況下觸發(fā)遞歸的方法,或者是不希望被外部函數(shù)訪問到的情況。因為作為內(nèi)部函數(shù)是不會被外部函數(shù)所訪問到的。
擴(kuò)展函數(shù)
擴(kuò)展函數(shù)數(shù)是指在一個類上增加一種新的行為,甚至我們沒有這個類代碼的訪問權(quán)限。這是一個在缺少有用函數(shù)的類上擴(kuò)展的方法,Kotlin能夠為我們做到那些令人關(guān)注的事情,而這些Java做不到。簡單來說,Kotlin擴(kuò)展函數(shù)允許我們在不改變已有類的情況下,為類添加新的函數(shù)。
fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT){
Toast.makeText(this, message, duration).show()
}
看到在這里我們寫了一個擴(kuò)展函數(shù)toast;這個函數(shù)基于Activity這個類中進(jìn)行的擴(kuò)展,參數(shù)有兩個,一個為需要顯示的內(nèi)容文字,另一個為顯示的時長。
當(dāng)我們在調(diào)用這個函數(shù)的時候可以直接調(diào)用
override fun onCreate(savedInstanceState: Bundle?) {
super<BaseActivity>.onCreate(savedInstanceState)
toast("This is onCreate!!")
toast("Hello world!", Toast.LENGTH_LONG)
}
我們可以在任何地方(例如在一個工具類文件中)聲明這個函數(shù),然后在我們的Activity中將它作為普通方法來直接使用。
有一點值得注意:擴(kuò)展函數(shù)并不是真正地修改了原來的類,它的這些作用效果是以靜態(tài)導(dǎo)入的方式來實現(xiàn)的。擴(kuò)展函數(shù)可以被聲明在任何文件中,因此有個通用的方式是把一系列有關(guān)的函數(shù)放在一個新建的文件里,就像我們剛才所說的工具類當(dāng)中。
例如我們在使用圖片的時候也可以用擴(kuò)展函數(shù)來處理
fun ImageView.loadImage(context: Context, path: String, placeholder: Int = R.mipmap.ic_launcher, useCache: Boolean =false) {
var options = getOptions(placeholder, useCache)
Glide.with(context).load(path).apply(options).into(this)
}
看到我們在常用的Glide圖片庫時候,可以通過擴(kuò)展庫來處理,并且指定默認(rèn)的控件id、圖片地址、是否使用緩存等等一系列操作。這么用起來是不是特別舒服呢?
高階函數(shù)
高階函數(shù)是指,函數(shù)的參數(shù)又是一個函數(shù),所以稱之為高階函數(shù)。比如 lock() 就是一個很好的例子,它接收一個 lock 對象和一個函數(shù),運行函數(shù)并釋放 lock;
fun <T> lock(lock: Lock, body: () -> T ) : T {
lock.lock()
try {
return body()
}
finally {
lock.unlock()
}
}
現(xiàn)在解釋一下上面的代碼吧:body 有一個函數(shù)類型 () -> T,把它設(shè)想為沒有參數(shù)并返回 T 類型的函數(shù)。它引發(fā)了內(nèi)部的 try 函數(shù)塊,并被 lock 保護(hù),結(jié)果是通過 lock() 函數(shù)返回的。 如果我們想調(diào)用 lock() ,函數(shù),我們可以傳給它另一個函數(shù)做參數(shù)
fun toBeSynchroized() = sharedResource.operation()
val result = lock(lock, ::toBeSynchroized)
其實最方便的辦法是傳遞一個字面函數(shù)(通常是 lambda 表達(dá)式):
val result = lock(lock, {
sharedResource.operation() })
如果覺得我的文章能夠幫助到你,也歡迎關(guān)注我的微信公眾號「晨雨細(xì)曲」,有新技術(shù)和知識會推送在這上面。