kotlin學(xué)習(xí)第三天

運(yùn)算符重載

kotlin中每一個(gè)運(yùn)算符對應(yīng)一個(gè)方法。比如我們想把兩個(gè)對象加起來的話掺涛,只需要把“+”對應(yīng)的方法復(fù)寫就可以實(shí)現(xiàn)了。運(yùn)算符對應(yīng)的方法可以通過kotlin官網(wǎng)http://kotlinlang.org/docs/reference查詢。

fun main(args: Array<String>) {
    val p1 = Person()
    val p2 = Person()
    p1.age = 10
    p2.age = 20
    //求p1和p2的年齡和
    var plus = p1.plus(p2)
    println(plus)
}
//重寫“+”方法
class Person {
    var name = "張三"
    var age = 0

    fun plus(person: Person): Int {
        return age + person.age
    }
}

類的成員

類成員可以訪問并且修改岗仑,kotlin的類成員變量默認(rèn)已經(jīng)實(shí)現(xiàn)了get以及set方法。

成員的訪問與修改

由于kotlin的類成員變量默認(rèn)實(shí)現(xiàn)get以及set方法聚请,所以類中的成員可以直接調(diào)用:

fun main(args: Array<String>) {
    val stu = Student()
    println(stu.age)
    println(stu.name)
}

class Student {
    val name = "張三"
    val age = 15
}

修改類成員的可見性

在Kotlin中荠雕,若是想要類成員對于外界只能訪問不能修改,則在類成員后中寫入 private set。若想類成員對外界既不能訪問也不能修改炸卑,則在類成員前寫入private:

class Student {
    var name = "張三"
    private set//外界無法修改name
    private var age = 15//外界無法訪問既鞠、修改age
}

自定義訪問器

在我們的例子中,學(xué)生的年齡不可能隨意設(shè)置盖文,比如學(xué)生是-1歲损趋,所以需要對設(shè)置的數(shù)據(jù)進(jìn)行判定,符合一定要求后才能修改椅寺。對于此類要求浑槽,我們可以用自定義訪問器field:

fun main(args: Array<String>) {
    var person = Student()
    println(person.age)//20
    person.age = 35//由于35>30,所以設(shè)置失敗
    println(person.age)//20

}

class Student {
    var name = "張三"
    var age = 20
        set(value) {//value對應(yīng)傳遞的age值
            if (value > 18 && value < 30) {
                //可以通過field表示這個(gè)字段
                field = value
            }
        }
}

主構(gòu)函數(shù)和次構(gòu)函數(shù)

主構(gòu)函數(shù)

kotlin中主構(gòu)函數(shù)即構(gòu)造函數(shù)返帕,但是無法直接訪問構(gòu)造函數(shù)中的元素桐玻。如果想要在構(gòu)造函數(shù)里面實(shí)現(xiàn)一些操作,需要把代碼寫在init里:

fun main(args: Array<String>) {
    val p1 = Person("張三", 23)
    val p2 = Person("李四", 25)
    val p3 = Person("王五", 40)
    println(p1.age)//23
    println(p2.age)//25
    println(p3.age)//40
}

class Person(name: String, age: Int) {
    var name = ""
    var age = 0

    init {
        this.age = age
        this.name = name
    }
}

var和val在主構(gòu)函數(shù)參數(shù)中的作用

主構(gòu)函數(shù)參數(shù)使用var和val荆萤,相當(dāng)于幫我們定義了字段镊靴,參數(shù)可以直接使用。參數(shù)沒有var和val修飾链韭,參數(shù)在其他地方不能使用 偏竟。參數(shù)有var修飾,可以使用敞峭,也可以修改 踊谋。參數(shù)有val修飾,只能使用旋讹,不能修改 :

fun main(args: Array<String>) {
    val p1 = Person("張三", 23)
    val p2 = Person("李四", 25)
    val p3 = Person("王五", 40)
    println(p1.age)
    println(p2.age)
    println(p3.age)
}

class Person(val name: String,val age: Int)

次構(gòu)函數(shù)

次構(gòu)函數(shù)必須要調(diào)用主構(gòu)函數(shù)殖蚕,必須要把參數(shù)傳遞給主構(gòu)函數(shù),且需要用constructor關(guān)鍵字:

class Person2(val name: String,val age: Int){
    constructor(name: String, age: Int,phone:String):this (name,age)//調(diào)用主構(gòu)函數(shù)將參數(shù)傳遞給主構(gòu)函數(shù)
}

次構(gòu)函數(shù)間調(diào)用

次構(gòu)函數(shù)可以直接調(diào)用主構(gòu)函數(shù)沉迹,也可以通過調(diào)用次構(gòu)函數(shù)來間接調(diào)用主構(gòu)函數(shù):

class Person3(name:String,age: Int){
    //調(diào)用主構(gòu)函數(shù)
    constructor(name:String,age: Int,phone: String):this(name,age)
    //通過調(diào)用次構(gòu)函數(shù)來間接調(diào)用主構(gòu)函數(shù)
    constructor(name:String,age: Int,phone: String,qq:String):this(name,age,phone)
}

次構(gòu)函數(shù)參數(shù)使用

構(gòu)造函數(shù)加var和val只能在主構(gòu)函數(shù)里面加睦疫,次構(gòu)函數(shù)中不能加。主構(gòu)函數(shù)參數(shù)可以直接加上var和val使用鞭呕,次構(gòu)函數(shù)只能夠自己定義變量進(jìn)行保存蛤育。

class Person3(val name:String,val age: Int){
    var phone = ""
    var qq = ""
    constructor(name:String,age: Int,phone: String):this(name,age)
    constructor(name:String,age: Int,phone: String,qq:String):this(name,age,phone){
        this.phone = phone
        this.qq = qq
    }
}

繼承

繼承是指一個(gè)對象直接使用另一對象的屬性和方法。kotlin的繼承和java中的繼承大體相同葫松,但需要注意以下幾點(diǎn):

1.需要將父類加上open關(guān)鍵字

2.需要加上():

kotlin的成員函數(shù)和成員變量對應(yīng)的get以及set方法都有final修飾瓦糕,不能進(jìn)行繼承,所以要在成員函數(shù)和成員變量前加上open關(guān)鍵字才能進(jìn)行復(fù)寫:

open class father() {
    open var name = "小頭爸爸"
    open var age = 40
    open fun sayHello() {
        println("老哥 早上好")
    }

}

class son : father() {
    override var name: String = "大頭兒子"
    override var age: Int = 14
    override fun sayHello() {
        println("同學(xué) 早上好")
    }

}

構(gòu)造函數(shù)的繼承

構(gòu)造函數(shù)的繼承除了通常的操作外进宝,子類也需要構(gòu)造函數(shù)刻坊,并且應(yīng)能在父類中找到對應(yīng)的字段,還需將函數(shù)傳給父類党晋。子類也可以用父類的字段:

fun main(args: Array<String>) {
    var p = Person("張三", 30)
    var s = Student("李四", 20, "男")
    println(p.age)//30
    println(s.sex)//男
    println(s.name)//李四

}

open class Person(var name: String, var age: Int) {
    open fun morning() {
        println("早上好")
    }
}

class Student(name: String, age: Int, var sex: String) : Person(name, age) {
    override fun morning() {
        println("晚上好")
    }
}

抽象類和抽象方法

父類中的方法,被它的子類們重寫,子類各自的實(shí)現(xiàn)都不盡相同未玻。那么父類的方法聲明和方法主體灾而,只有聲明還有意義,而方法主體則沒有存在的意義了扳剿。我們把沒有方法主體的方法稱為抽象方法旁趟。包含抽象方法的類就是抽象類。抽象類不需要open關(guān)鍵字就可以被調(diào)用庇绽。

//人類 (抽象類)
abstract class Human {
    abstract var color: String
    abstract var language: String
    abstract fun eat()
}

//具體實(shí)現(xiàn)類
class Chinese : Human() {
    override var color: String = "yellow"
    override var language: String = "chinese"

    override fun eat() {
        println("用筷子吃飯")
    }
}

class USHuman : Human() {
    override var color: String = "white"
    override var language: String = "english"

    override fun eat() {
        println("用刀叉吃飯")
    }
}

class AfHuman : Human() {
    override var color: String = "black"
    override var language: String = "葡萄牙語"

    override fun eat() {
        println("用手吃飯")
    }
}

接口

接口的實(shí)現(xiàn)是在括號(hào)后面加個(gè)冒號(hào)锡搜,然后寫上要實(shí)現(xiàn)的接口,不需要寫interface瞧掺。若是多個(gè)接口耕餐,就用逗號(hào)“,”隔開辟狈。

class men() : bike {
    override fun rideBike() {
        println("人騎車")
    }

}

interface bike {
    fun rideBike()
}

注意事項(xiàng)

1.java中接口中的字段一定要被賦值肠缔,但是Kotlin接口里的字段不能被賦值

2.java接口里面方法不能實(shí)現(xiàn),kotlin可以實(shí)現(xiàn)

class men() : Bike, Drive {
    override val license: String = "123456"
    override fun drive() {
        println("人開車")
    }
    override fun rideBike() {
        println("人騎車")
    }

}

interface Bike {
    fun rideBike()
}

interface Drive {
    val license: String
    fun drive() {
        println("放手剎,踩油門,走")
    }
}

多態(tài)

同種功能的不同表現(xiàn)形式哼转。kotlin中的多態(tài)原理同java:

abstract class Animal {
    abstract var name: String

    open fun bark() {
        println("動(dòng)物叫")
    }
}

class Dog : Animal() {
    override var name: String = "旺財(cái)"

    override fun bark() {
        println("旺財(cái)  汪汪叫")
    }
}

class Cat : Animal() {
    override var name: String = "湯姆"

    override fun bark() {
        println("湯姆  喵喵叫")
    }
}

智能類型轉(zhuǎn)換

在多態(tài)中明未,多個(gè)子類可能均與父類有差別。kotlin中可以通過智能類型推斷來判斷調(diào)用的字段所屬于的子類壹蔓,最終調(diào)用所屬子類的方法趟妥。將父類引用轉(zhuǎn)為子類引用,轉(zhuǎn)換之前還需要判斷是否是當(dāng)前子類類型佣蓉。一旦判斷出是這個(gè)類型之后煮纵,編譯器就把類型轉(zhuǎn)換過去了,不需要手動(dòng)轉(zhuǎn)換偏螺。

fun main(args: Array<String>) {
    val shepHerdDog: Dog = ShepHerdDog()//將父類引用轉(zhuǎn)為子類引用
    //判斷是否是當(dāng)前子類類型
    if (!(shepHerdDog is ShepHerdDog)) return
    //編譯器自動(dòng)轉(zhuǎn)換
    shepHerdDog.shepHerd()
}

abstract class Dog

class ShepHerdDog : Dog() {
    fun shepHerd() {
        println("牧羊犬開始放羊了...")
    }
}

嵌套類行疏、內(nèi)部類

嵌套類默認(rèn)都是static修飾的,屬于靜態(tài)類套像,不依賴于外部的環(huán)境酿联,即和外部類沒有關(guān)系:

fun main(args: Array<String>) {
    val inClass = outClass()
}

class outClass {
    var name: String = "李四"

    class inClass {
        fun say() {
            println(name)
        }
    }
}

內(nèi)部類需要通過Inner修飾,且需要先創(chuàng)建出來外部環(huán)境:

fun main(args: Array<String>) {
    val inClass = outClass.inClass()
}

class outClass {
    var name: String = "李四"
    inner class inClass {
        fun say() {
            println(name)
        }
    }
}

內(nèi)部類中使用this

如上例夺巩,若內(nèi)部類中也有一個(gè)var name = "張三"贞让,則默認(rèn)情況下會(huì)打印張三,即從最近開始找柳譬。如果我們想訪問外部類中的name喳张,也就是李四。這時(shí)候就需要把打印內(nèi)容改為外部類名.this.namethis@outClass.name:

class OutClass {
    var name = "李四"

    inner class InClass {
        var name = "張三"
        fun sayHello() {
            println(this@OutClass.name)
            //或
            println(OutClass.this.name)
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末美澳,一起剝皮案震驚了整個(gè)濱河市销部,隨后出現(xiàn)的幾起案子摸航,更是在濱河造成了極大的恐慌,老刑警劉巖舅桩,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酱虎,死亡現(xiàn)場離奇詭異,居然都是意外死亡擂涛,警方通過查閱死者的電腦和手機(jī)读串,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撒妈,“玉大人恢暖,你說我怎么就攤上這事≌遥” “怎么了杰捂?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長挟阻。 經(jīng)常有香客問我琼娘,道長,這世上最難降的妖魔是什么附鸽? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任脱拼,我火速辦了婚禮,結(jié)果婚禮上坷备,老公的妹妹穿的比我還像新娘熄浓。我一直安慰自己,他們只是感情好省撑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布赌蔑。 她就那樣靜靜地躺著,像睡著了一般竟秫。 火紅的嫁衣襯著肌膚如雪娃惯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天肥败,我揣著相機(jī)與錄音趾浅,去河邊找鬼。 笑死馒稍,一個(gè)胖子當(dāng)著我的面吹牛皿哨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纽谒,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼证膨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鼓黔?” 一聲冷哼從身側(cè)響起央勒,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤不见,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后订歪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脖祈,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肆捕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年刷晋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慎陵。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡眼虱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出席纽,到底是詐尸還是另有隱情捏悬,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布润梯,位于F島的核電站过牙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纺铭。R本人自食惡果不足惜寇钉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舶赔。 院中可真熱鬧扫倡,春花似錦、人聲如沸竟纳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锥累。三九已至缘挑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桶略,已是汗流浹背语淘。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留删性,地道東北人亏娜。 一個(gè)月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像蹬挺,于是被迫代替她去往敵國和親维贺。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354