欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Kotlin擴(kuò)展函數(shù)與運(yùn)算符重載超詳細(xì)解析

 更新時(shí)間:2022年11月24日 10:36:17   作者:發(fā)飆的蝸牛YR  
Kotlin可以為一個(gè)不能修改的或來(lái)自第三方庫(kù)中的類編寫一個(gè)新的函數(shù)。這個(gè)新增的函數(shù)就像那個(gè)原始類本來(lái)就有的函數(shù)一樣,可以用普通的方法調(diào)用,這種機(jī)制的函數(shù)稱為擴(kuò)展函數(shù)

一、擴(kuò)展函數(shù)

不少現(xiàn)代高級(jí)編程語(yǔ)言中有擴(kuò)展函數(shù)這個(gè)概念,Java卻一直以來(lái)都不支持這個(gè)功能,Kotlin對(duì)擴(kuò)展函數(shù)有了很好的支持。

擴(kuò)展函數(shù)表示即使在不修改某個(gè)類的源碼的情況下,仍然可以打開這個(gè)類,向該類添加新的函數(shù)。

比如有一個(gè)功能:一段字符串中可能包含字母、數(shù)字和特殊符號(hào)等字符,現(xiàn)在我們希望統(tǒng)計(jì)字符串中字母的數(shù)量,要怎么實(shí)現(xiàn)這個(gè)功能?如果按照一般的編程思維,可能會(huì)很自然的寫出如下函數(shù):

object StringUtil{
    fun  lettersCount(str:String):Int{
        var count=0
        for(char in str){
            if(char.isLetter()){
                count++
            }
        }
        return count
    }
}

這里先定義了一個(gè)StringUtil單例類,然后在這個(gè)單例類中定義一個(gè)lettersCount()函數(shù),該函數(shù)接收一個(gè)字符串參數(shù)。在lettersCount()方法中,我們使用for-in循環(huán)去遍歷字符串中的每一個(gè)字符。如果該字符是一個(gè)字母的話,那么計(jì)數(shù)器加1,最終返回計(jì)數(shù)器的值。

現(xiàn)在我們需要統(tǒng)計(jì)某個(gè)字符串中的字母數(shù)量時(shí),只需要編寫如下代碼:

 val str="ABCdsw1242"
 val Count = StringUtil.lettersCount(str)

這種寫法可以正常工作,這也是Java編程中的標(biāo)準(zhǔn)實(shí)現(xiàn)思維,但有了擴(kuò)展函數(shù)之后就不一樣了,我們可以使用一種更加面向思維來(lái)實(shí)現(xiàn)這個(gè)功能,比如說(shuō)lettersCount()函數(shù)添加到String類當(dāng)中。

我們先來(lái)學(xué)習(xí)一下定義擴(kuò)展函數(shù)的語(yǔ)法結(jié)構(gòu),如下所示:

fun ClassName.methodName(param1:Int,param2:Int):Int{
return 0
}

想定義普通的函數(shù),定義擴(kuò)展函數(shù)只需要在函數(shù)名的前面加上一個(gè)ClassName.的語(yǔ)法結(jié)構(gòu),就表示將該函數(shù)添加到指定類當(dāng)中。

接下來(lái)使用擴(kuò)展函數(shù)的方式來(lái)優(yōu)化剛才的統(tǒng)計(jì)功能。

由于我們希望向String類中添加一個(gè)擴(kuò)展函數(shù),因此需要先創(chuàng)建一個(gè)String.kt文件。文件名雖然沒(méi)有固定的要求,但是我建議向哪個(gè)類中添加擴(kuò)展函數(shù),就定義一個(gè)同名的Kotlin文件,這樣便于你以后查找。當(dāng)前,擴(kuò)展函數(shù)也是可以定義在任何一個(gè)現(xiàn)有類當(dāng)中的,并不一定非要?jiǎng)?chuàng)建新文件。不過(guò)通常來(lái)說(shuō),最好將它定義成頂層方法,這樣可以讓擴(kuò)展函數(shù)擁有全局的訪問(wèn)域。

現(xiàn)在在String.kt文件中編寫如下代碼:

fun String.lettersCount():Int{
var count=0
for(char in this){
if(char.isLetter()){
count++
}
}
return count
}

注意這里的代碼變化,現(xiàn)在我們將lettersCount()方法定義成了String類的擴(kuò)展函數(shù),那么函數(shù)中就自動(dòng)擁有了String實(shí)例的上下文。因此lettersCount()函數(shù)就不再需要接收一個(gè)字符串參數(shù)了,而是直接遍歷this即可,因?yàn)楝F(xiàn)在this就代表著字符串本身。

定義好了擴(kuò)展函數(shù)之后,統(tǒng)計(jì)某個(gè)字符串中的字母數(shù)量只需要這樣寫即可:

val count="ABCdsw1242".lettersCount()

這樣看上去是String類中自帶了lettersCount()方法一樣。

擴(kuò)展函數(shù)在很多情況下可以讓API變得更加簡(jiǎn)潔、豐富,更加面向?qū)ο?。我們?cè)俅我許tring類為例,這是一個(gè)final類,任何一個(gè)類都不可以繼承它,也就是說(shuō)它的API只有固定的那些而已,至少在Java中就是如此。然而到了Kotlin中就不一樣了,我們可以向Kotlin類中擴(kuò)展任何函數(shù),使他的API變得更加豐富。比如,你會(huì)發(fā)現(xiàn)Kotlin中的String甚至還有reverse()函數(shù)用于反轉(zhuǎn)字符串,capitalize()函數(shù)用于對(duì)首字母進(jìn)行大寫,等等,這都是Kotlin語(yǔ)言自帶的一些擴(kuò)展函數(shù)。

二、運(yùn)算符重載

在Java中有許多語(yǔ)言內(nèi)置的運(yùn)算符關(guān)鍵字,如+,-,*,/,%,++,–。而Kotlin允許我們將所有的運(yùn)算符甚至其他的關(guān)鍵字進(jìn)行重載,從而拓展這些運(yùn)算符和關(guān)鍵字的用法。

我們基本上都使用過(guò)加減乘除這種四則運(yùn)算符,在編程語(yǔ)言里面,兩個(gè)數(shù)字相加表示求這兩個(gè)數(shù)字之和,兩個(gè)字符串相加表示對(duì)這兩個(gè)字符串進(jìn)行拼接。但是在Kotlin語(yǔ)言中,kotlin運(yùn)算符重載卻允許我們讓任意兩個(gè)對(duì)象相加,或者進(jìn)行更多其他的運(yùn)算操作。

運(yùn)算符重載使用的是operator關(guān)鍵字,只要在指定函數(shù)的前面加上operator關(guān)鍵字,就可以實(shí)現(xiàn)運(yùn)算符重載的功能了。但問(wèn)題是在于這個(gè)指定函數(shù)是什么?這是運(yùn)算符重載里面比較復(fù)雜的一個(gè)問(wèn)題,因?yàn)椴煌倪\(yùn)算符對(duì)應(yīng)的重載函數(shù)也是不同的。比如說(shuō)加號(hào)運(yùn)算符對(duì)應(yīng)的是plus()函數(shù),減號(hào)運(yùn)算符對(duì)應(yīng)的是minus()函數(shù)。

我們這里還是以加號(hào)運(yùn)算符為例,如果想要實(shí)現(xiàn)讓兩個(gè)對(duì)象相加的功能,那么它的語(yǔ)法結(jié)構(gòu)如下:

class obj{
   operator fun plus(obj:Obj):Obj{
  //處理相加的邏輯
}
}

在上述的語(yǔ)法結(jié)構(gòu)中,關(guān)鍵字operator和函數(shù)名plus都是固定不變的,而接收的參數(shù)和函數(shù)返回值可以根據(jù)你的邏輯自行設(shè)定。那么上述代碼就表示一個(gè)Obj對(duì)象可以與另一個(gè)Obj對(duì)象相加,最終返回一個(gè)新的Obj對(duì)象。對(duì)應(yīng)的調(diào)用方式如下:

val obj1=Obj()
val obj2=Obj()
val obj3=obj1+obj2

這種obj1+obj2的語(yǔ)法其實(shí)就是Kotlin給我們提供的一種語(yǔ)法糖,它會(huì)在編譯的時(shí)候被轉(zhuǎn)換成obj1.plus(obj2)的調(diào)用方式。

舉一個(gè)例子實(shí)現(xiàn)讓兩個(gè)Money對(duì)象相加

首先定義Money類的結(jié)構(gòu),這里讓Money的主構(gòu)造函數(shù)接收一個(gè)value參數(shù),用于表示錢的金額。創(chuàng)建Money.kt文件,代碼如下所示:

class Money(val value:Int)

定義好了Money類的結(jié)構(gòu),接下來(lái)我們就使用運(yùn)算符來(lái)重載實(shí)現(xiàn)讓兩個(gè)Money對(duì)象相加的功能:

class Money(val value:Int) {
    operator fun plus(money: Money):Money{
        val sum=value+money.value
        return Money(sum)
    }   
}

可以看到,這里使用了operator關(guān)鍵字來(lái)修飾plus()函數(shù),這是必不可少的。在plus()函數(shù)中,我們將當(dāng)前Money對(duì)象的value和參數(shù)傳入的Money對(duì)象的value相加,然后將得到的和傳入給一個(gè)新的Money對(duì)象并將該對(duì)象返回。這樣兩個(gè)Money對(duì)象就可以相加了。

我們可以使用如下代碼進(jìn)行測(cè)試

 val money1 = Money(5)
 val money2 = Money(10)
 val money3=money1+money2
 println(money3.value)

最終結(jié)果為15

Money對(duì)象能夠直接和數(shù)字相加,因?yàn)镵otlin允許我們對(duì)同一個(gè)運(yùn)算符進(jìn)行多重重載,代碼如下:

class Money(val value:Int) {
    operator fun plus(money: Money):Money{
        val sum=value+money.value
        return Money(sum)
    }
    //對(duì)同一個(gè)運(yùn)算符進(jìn)行多重重載
    operator fun plus(newValue:Int):Money{
        val sum=value+newValue
        return Money(sum)
    }
}

這里我們又重載了一個(gè)plus()函數(shù),不過(guò)這次接收的參數(shù)是一個(gè)整型數(shù)字,其他代碼基本一樣。

那么現(xiàn)在Money對(duì)象就擁有了和數(shù)字相加的能力:

 val money1 = Money(5)
 val money2 = Money(10)
 val money3=money1+money2
 val money4=money3+20
 println(money4.value)

打印結(jié)果為35

Kotlin允許我們重載的運(yùn)算符和關(guān)鍵字多達(dá)十幾個(gè)。表中列出了所有可能常用的可重載運(yùn)算符和關(guān)鍵字對(duì)應(yīng)的語(yǔ)法糖表達(dá)式,以及它們會(huì)被轉(zhuǎn)換成的實(shí)際調(diào)用函數(shù)。如果想重載其中的某一種運(yùn)算符或關(guān)鍵字,只要參考剛才加號(hào)運(yùn)算符重載的寫法去實(shí)現(xiàn)就行了。

語(yǔ)法糖表達(dá)式實(shí)際調(diào)用函數(shù)
a+ba.plus(b)
a-ba.minus(b)
a*ba.times(b)
a/ba.div(b)
a%ba.rem(b)
a++a.inc()
a–a.dec()
+aa.unaryPlus
-aa.unaryMinus
!aa.not
a==ba.equals(b)
a>=ba.compareTo(b)
a…ba.rangeTo(b)
a[b]a.get(b)
a[b]=ca.set(b,c)
a in bb.contains(a)

注意,最后一個(gè)a in b的語(yǔ)法糖表達(dá)式對(duì)應(yīng)的實(shí)際調(diào)用函數(shù)是b.contains(a),a、b對(duì)象順序是反過(guò)來(lái)的。因?yàn)閍 in b表示判斷a是否在b當(dāng)中,而b.contains(a)表示b是否包含a,因此這兩種表達(dá)式是等價(jià)的。

舉個(gè)例子,Kotlin中的String類就對(duì)contains()函數(shù)進(jìn)行了重載,因此當(dāng)我們判斷“hello”字符串中是否包含“he”子串時(shí),首先可以這樣寫:

if("hello".contains("he")){
}

而借助重載的語(yǔ)法糖表達(dá)式,也可以這樣寫:

if("he" in "hello"){
}

結(jié)合學(xué)習(xí)的擴(kuò)展函數(shù)以及運(yùn)算符重載的知識(shí),對(duì)以下功能進(jìn)行優(yōu)化

fun getRandomLengthString(str:String):String{
val n=(1..20).random()
val builder=StringBuilder()
repeat(n){
builder.append(str)
}
return builder.toString()
}

其實(shí)這個(gè)函數(shù)的核心思想就是將傳入的字符串重復(fù)n次,而Kotlin能夠讓我們使用str*n這種寫法來(lái)表示讓str字符串重復(fù)n次,使語(yǔ)法更精簡(jiǎn)。

要讓一個(gè)字符串可以乘以一個(gè)數(shù)字,那么肯定要在String類中重載乘號(hào)運(yùn)算符才行,但是String類是系統(tǒng)提供的類,我們無(wú)法修改這個(gè)類的代碼。這個(gè)時(shí)候就可以借助擴(kuò)展函數(shù)功能向String類中添加新函數(shù)了。

既然是向String類中添加擴(kuò)展函數(shù),那么我們還是打開剛才創(chuàng)建的String.kt文件,然后加入如下代碼:

operator fun String.times(n:Int):String{
val builder=StringBuilder()
repeat(n){
builder.append(this)
}
return builder.toString()
} 

首先,operator關(guān)鍵字肯定是必不可少的,然后是要重載乘號(hào)運(yùn)算符,參考上面的表,如果要乘那么函數(shù)名必須是times,最后由于是定義擴(kuò)展函數(shù),因此還要在方法名前面加上String.的語(yǔ)法結(jié)構(gòu)。在times()函數(shù)中,我們借助StringBuilder和repeat函數(shù)將字符串重復(fù)n次,最終將結(jié)果返回。

現(xiàn)在,字符串就有了和一個(gè)數(shù)字相乘的能力,比如執(zhí)行如下代碼:

val str="abc"*3
println(str)

最終打印結(jié)果是:abcabcabc。

現(xiàn)在我們就可以在getRandomLengthString()函數(shù)中使用這種寫法了

operator fun String.times(n:Int)=str*(1..20).random()

另外,必須說(shuō)明的是,其實(shí)Kotlin的String類中已經(jīng)提供了一個(gè)用于將字符串重復(fù)n遍的repeat()函數(shù),因此times()函數(shù)還可以進(jìn)一步精簡(jiǎn)成如下形式:

operator fun String.times(n:Int)=repeat(n)

到此這篇關(guān)于Kotlin擴(kuò)展函數(shù)與運(yùn)算符重載超詳細(xì)解析的文章就介紹到這了,更多相關(guān)Kotlin擴(kuò)展函數(shù)與運(yùn)算符重載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Flutter實(shí)現(xiàn)底部導(dǎo)航欄效果

    Flutter實(shí)現(xiàn)底部導(dǎo)航欄效果

    這篇文章主要為大家詳細(xì)介紹了Flutter實(shí)現(xiàn)底部導(dǎo)航欄效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Android編程實(shí)現(xiàn)圖標(biāo)拖動(dòng)效果的方法

    Android編程實(shí)現(xiàn)圖標(biāo)拖動(dòng)效果的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)圖標(biāo)拖動(dòng)效果的方法,涉及Android事件響應(yīng)及圖標(biāo)變換的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • Andriod Service與Thread的區(qū)別介紹

    Andriod Service與Thread的區(qū)別介紹

    我們要明確Service是運(yùn)行在主線程的,不能有耗時(shí)操作,這樣,在Service中處理耗時(shí)操作的時(shí)候,我們依然需要使用線程來(lái)處理,既然在Service里也要?jiǎng)?chuàng)建一個(gè)子線程,那為什么不直接在Activity里創(chuàng)建呢,下面通過(guò)本文給大家介紹Andriod Service與Thread的區(qū)別,一起看看吧
    2017-04-04
  • 詳解React Native監(jiān)聽Android回退按鍵與程序化退出應(yīng)用

    詳解React Native監(jiān)聽Android回退按鍵與程序化退出應(yīng)用

    這篇文章主要介紹了詳解React Native監(jiān)聽Android回退按鍵與程序化退出應(yīng)用的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Flutter?fluro時(shí)報(bào)錯(cuò)type?'String'?is?not?a?subtype?of?type?'Queue<Task>'

    Flutter?fluro時(shí)報(bào)錯(cuò)type?'String'?is?not?a?subty

    這篇文章主要介紹了Flutter使用fluro時(shí)報(bào)錯(cuò)type?'String'?is?not?a?subtype?of?type?'Queue<Task>'解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2023-12-12
  • Android編程之MD5加密算法實(shí)例分析

    Android編程之MD5加密算法實(shí)例分析

    這篇文章主要介紹了Android編程之MD5加密算法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android使用MD5加密的具體實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • Android Studio Gradle插件版本與Gradle版本之間的對(duì)應(yīng)關(guān)系

    Android Studio Gradle插件版本與Gradle版本之間的對(duì)應(yīng)關(guān)系

    今天小編就為大家分享一篇關(guān)于Android Studio Gradle插件版本與Gradle版本之間的對(duì)應(yīng)關(guān)系,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • Android利用Java優(yōu)雅消除復(fù)雜條件表達(dá)式的方法

    Android利用Java優(yōu)雅消除復(fù)雜條件表達(dá)式的方法

    這篇文章主要介紹了Android利用Java優(yōu)雅消除復(fù)雜條件表達(dá)式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值。感興趣的小伙伴可以參考一下
    2022-06-06
  • onMeasure被執(zhí)行兩次原理解析

    onMeasure被執(zhí)行兩次原理解析

    這篇文章主要為大家介紹了onMeasure被執(zhí)行兩次原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Android開發(fā)使用Messenger及Handler進(jìn)行通信的方法示例

    Android開發(fā)使用Messenger及Handler進(jìn)行通信的方法示例

    這篇文章主要介紹了Android開發(fā)使用Messenger及Handler進(jìn)行通信的方法,結(jié)合實(shí)例形式分析了Android使用Messenger及Handler定義客戶端與服務(wù)器端實(shí)現(xiàn)通信的相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12

最新評(píng)論