Kotlin語言(五):類和對象

1家凯、面向?qū)ο?/h4>
/**
 * 任何復雜的數(shù)據(jù)類型都是由基本數(shù)據(jù)類型組成的
 * 面向?qū)ο笞钪匾奶攸c:用基本的數(shù)據(jù)類型描述復雜的事物
 *
 * 1.定義對象用class關(guān)鍵字
 * 2.對象一般都有靜態(tài)屬性和動態(tài)行為绊诲,但不是必須具備
 */

class Rect {}

class Boy {
    //靜態(tài)屬性
    var name: String = "張三"
    var age: Int = 20
}

class Girl {
    //動態(tài)行為
    fun greeting() {
        println("你好葫督!")
    }
}

class People {
    //靜態(tài)屬性
    var name: String = "王五"
    var age: Int = 20

    //動態(tài)行為
    fun greeting() {
        println("你好橄镜!")
    }
}

fun main() {
    val rect = Rect()
    val boy = Boy()
    val girl = Girl()
    val people = People()
    println(people.name)
    println(people.age)
    people.greeting()
}

2冯乘、屬性的get和set

/**
 * 1洽胶、通過反編譯成java代碼裆馒,發(fā)現(xiàn)kotlin的字段都是私有的,并且會自動生成get和set方法
 */
class Person0 {
    var name = "張三"
    var age = 18
}

/**
 * 2喷好、修改get和set的可見性
 */
class Person1 {
    var name = "張三"
        private set//把name的set方法私有化,即name只能訪問不能修改

    var age = 18
    val sex = true
}

/**
 * 3梗搅、自定義get和set訪問器
 * 注:這里要注意 field 字段的使用禾唁,直接賦值或者獲取值其實是調(diào)用的set和get方法,因而會進入無限遞歸調(diào)用
 */
class Person2 {
    var name = "張三"
    var age = 18
        set(value) {
            if (value in 0..150) {
                //age = value //這里直接賦值其實是調(diào)用的set方法荡短,所以會進入無限遞歸調(diào)用自己
                field = value
            } else {
                field = 0
            }
            //field = if (value in 0..150) value else 0 //if表達式
        }
}

fun main() {
    val person0 = Person0()
    println("name=${person0.name}  age=${person0.age}") //name=張三  age=18

    val person1 = Person1()
    //person1.name = "李四" //編譯報錯掘托,name的set方法私有化了闪盔,故不能修改其值
    //person1.sex = false   //sex為不可變變量锭沟,故不能修改识补,但是可以獲取
    val sex = person1.sex

    val person2 = Person2()
    person2.age = 200
    println("age=${person2.age}") //age=0凭涂,賦值超過了0-100祝辣,故設置為0
}

3、構(gòu)造函數(shù)

/**
 * 1切油、主構(gòu)造函數(shù)
 * (1)定義方式:直接跟在類名后面
 * (2)實現(xiàn)代碼:主要構(gòu)造函數(shù)的實現(xiàn)是在 init 關(guān)鍵字包含的代碼塊中
 */
class News0(title: String, content: String) {
    var title = ""
    var content = ""

    //主構(gòu)造函數(shù)的實現(xiàn)部分
    init {
        this.title = title
        this.content = content
    }
}

/**
 * 2蝙斜、主構(gòu)造函數(shù)參數(shù)使用 var 和 val
 * (1)構(gòu)造函數(shù)參數(shù)使用 var 或者 val 則會自動生成相應的成員變量
 * (2)使用 val 時只能在構(gòu)造函數(shù)里面賦值,后面不能再修改了
 */
class News1(var title: String, var content: String)

class News2(var title: String, val content: String)

/**
 * 3澎胡、次構(gòu)造函數(shù)
 * (1)次構(gòu)造函數(shù)使用 constructor 在類里面聲明
 * (2)次構(gòu)造函數(shù)后面可以使用 this 關(guān)鍵字調(diào)用其他次構(gòu)造函數(shù)或主構(gòu)造函數(shù)
 */
class News3(var title: String, val content: String) {
    var author = ""

    constructor(title: String, content: String, author: String) : this(title, content) {
        this.author = author
    }
}

/**
 * 4孕荠、構(gòu)造函數(shù)執(zhí)行順序:先執(zhí)行主構(gòu)函數(shù)的 init,再執(zhí)行次構(gòu)函數(shù)
 */
class News4(title: String, content: String) {
    var title = ""
    var content = ""
    var author = ""
    var date = ""

    //構(gòu)造函數(shù)的實現(xiàn)部分
    init {
        this.title = title
        this.content = content
        println("init執(zhí)行攻谁!")
    }

    constructor(title: String, content: String, author: String) : this(title, content) {
        this.author = author
        println("次構(gòu)造函數(shù)執(zhí)行稚伍!")
    }

    constructor(title: String, content: String, author: String, date: String) : this(
        title,
        content,
        author
    ) {
        this.date = date
        println("次構(gòu)造函數(shù)2執(zhí)行!")
    }

}


fun main() {
    val news0 = News0("王者榮耀", "S18賽季更新戚宦。")
    println("news0 [title=${news0.title}, content=${news0.content}]")
    //news0 [title=王者榮耀, content=S18賽季更新]

    val news1 = News1("QQ飛車", "11城來賽一場案鍪铩!")
    println("news1 [title=${news1.title}, content=${news1.content}]")
    //news1 [title=QQ飛車, content=11城來賽一場笆苈ァ垦搬!]
    val news2 = News2("QQ飛車", "11城來賽一場啊!")
    news2.title = "泡泡卡丁車" //編譯通過,var變量可以修改
    //news2.content = "中國龍賽場戰(zhàn)一場艳汽!" //編譯失敗猴贰,val變量不能修改

    val news3 = News3("歡樂斗地主", "來血戰(zhàn)到底啊河狐!", "騰訊")
    println("news3 [title=${news3.title}, content=${news3.content}, author=${news3.author}]")
    //news3 [title=歡樂斗地主, content=來血戰(zhàn)到底懊兹啤!, author=騰訊]

    val news4 = News4("皮皮麻將", "刮風甚牲、下雨义郑、碰碰碰!", "騰訊")
    println("news4 [title=${news4.title}, content=${news4.content}, author=${news4.author}]")
    //init執(zhí)行丈钙!
    //次構(gòu)造函數(shù)執(zhí)行非驮!
    //news4 [title=皮皮麻將, content=刮風、下雨雏赦、碰碰碰劫笙!, author=騰訊]

    val news5 = News4("皮皮麻將", "刮風、下雨星岗、碰碰碰填大!", "騰訊", "2020-12-20")
    println("news5 [title=${news5.title}, content=${news5.content}, author=${news5.author}, date=${news5.date}]")
    //init執(zhí)行!
    //次構(gòu)造函數(shù)執(zhí)行俏橘!
    //次構(gòu)造函數(shù)2執(zhí)行允华!
    //news5 [title=皮皮麻將, content=刮風、下雨、碰碰碰靴寂!, author=騰訊]
}

4磷蜀、封裝

/**
 * 所謂封裝就是隱藏內(nèi)部實現(xiàn)的細節(jié),暴露一些安全的接口給外部百炬;
 * 與 Java 一樣 kotlin 也是通過 private 關(guān)鍵字來隱藏內(nèi)部的實現(xiàn)細節(jié)
 */
class WashMachine(val brand: String, val capacity: Float) {

    // 這里的是否關(guān)門就是封裝褐隆,人們不能直接來修改這個屬性
    // 只能通過洗衣機提供的 openDoor() 和 closeDoor() 來控制
    private var isOpenDoor: Boolean = false

    fun openDoor() {
        isOpenDoor = true
        println("洗衣機門打開了")
    }

    fun closeDoor() {
        isOpenDoor = false
        println("洗衣機門關(guān)閉了")
    }

    fun startWash() {
        if (isOpenDoor){
            println("警告:沒有關(guān)門,不能開始洗衣服剖踊!")
        } else {
            println("放水 -> 開始洗衣服 -> 脫水烘干 -> 衣服洗好了")
        }
    }
}


fun main() {
    val washMachine = WashMachine("海爾", 12.0f)
    washMachine.openDoor() //洗衣機門打開了
    println("放衣服和臭襪子庶弃,倒入洗衣液")
    washMachine.startWash() //警告:沒有關(guān)門,不能開始洗衣服德澈!

    washMachine.closeDoor() //洗衣機門關(guān)閉了
    washMachine.startWash() //放水 -> 開始洗衣服 -> 脫水烘干 -> 衣服洗好了
}

5歇攻、繼承

/**
 * 1、類的繼承
 * (1)kotlin 的 class 默認都是 final 類型的圃验,不能被繼承
 * (2)只有被 open 關(guān)鍵字修飾的類才可以被繼承(關(guān)鍵字 open 的作用與 final 相反)
 * (3)kotlin 的 class 只能單繼承
 */
open class Parent0

class Child0 : Parent0()


/**
 * 2掉伏、初始化父類的構(gòu)造函數(shù)
 * (1)子類有主構(gòu)造函數(shù),則直接在主構(gòu)造函數(shù)后面初始化父類的構(gòu)造函數(shù)
 * (2)子類沒有主構(gòu)造函數(shù)澳窑,則需要使用 super 關(guān)鍵字或者調(diào)用其他的次構(gòu)造函數(shù)來初始化父類的構(gòu)造函數(shù)
 */
open class Parent1 {
    constructor()
    constructor(name: String)
    constructor(name: String, age: Int) : this(name)
}

class Child1_0 : Parent1() //class未定義構(gòu)造函數(shù)時會有一個默認的構(gòu)造函數(shù)斧散,此處為Child1_0()
class Child1_1(name: String) : Parent1(name)
class Child1_2(name: String, age: Int) : Parent1(name, age)
class Child1_3 : Parent1 {
    constructor() : super()
    constructor(name: String) : super(name)
    constructor(name: String, age: Int) : super(name, age)
    constructor(name: String, age: Int, sex: Boolean) : this(name, age)
}


/**
 * 3、方法的重寫
 * (1)kotlin 的 class 中的方法默認也是 final 類型摊聋,不能被重寫
 * (2)只有被 open 關(guān)鍵字修飾的方法才能被重寫
 * (3)重寫父類中 open 修飾的方法鸡捐,需在子類的方法前面加 override 關(guān)鍵字
 * (4)若在父類中方法 override 前再加上 final 后,子類中的該方法是不能被重寫的
 */
open class Parent2 {
    open fun todo() {
        println("Parent2的todo方法麻裁。")
    }
}

open class Child2_0 : Parent2() {
    final override fun todo() {
        super.todo()
        println("Child20的todo方法箍镜。")
    }
}

class Child2_1 : Child2_0() {
    //編譯報錯,final 方法不能被重寫
    /*override fun todo() {
        super.todo()
    }*/
}


/**
 * 4煎源、屬性的重寫
 * (1)只有被 open 關(guān)鍵字修飾的屬性才能被重寫
 * (2)var 屬性只能被 var 屬性重寫
 * (3)val 既可以被 var 屬性重寫色迂,也可以被val屬性重寫
 * (4)本質(zhì)上,val 相當于 get 方法手销,var 相當于 get 和 set 方法
 */
open class Parent3{
    open var name: String = "Parent3"
    open val nickName: String = "Parent3_nick"
    open val age: Int = 0
    var sex:Boolean = false
}

class Child3_0:Parent3(){
    override var name: String = "Child3_0"
    //override val name: String = "" //編譯失敗歇僧,var 不能重寫成 val
    override val nickName: String = "Child3_0_nick"
    override var age: Int = 10
    //override var sex: Boolean = true //編譯失敗,非 open 屬性不能重寫
}

6锋拖、抽象類

/**
 * 1诈悍、抽象類的定義和特點
 * (1)抽象類反映的是事物的本質(zhì)
 * (2)使用 abstract 表示抽象類、抽象屬性和抽象方法
 * (3)抽象類不能被實例化兽埃,即不能創(chuàng)建抽象類的對象
 * (4)抽象類可以有普通的方法和屬性
 * (5)抽象類侥钳、抽象屬性和抽象方法默認都是 open 的
 */
abstract class Human {
    abstract var color: String     //抽象屬性
    abstract var language: String  //抽象屬性
    open val sleep: Boolean = true //普通屬性

    abstract fun eat() //抽象方法
    fun walk() {       //普通方法
        println("人類都是用雙腳走路!")
    }
}


/**
 * 2柄错、抽象類的繼承
 * (1)抽象類只能單繼承
 * (2)抽象類也可以繼承抽象類
 * (3)繼承一個抽象類必須實現(xiàn)其所有的抽象方法和屬性舷夺,否則子類也必須聲明為抽象類
 */
class ZhHuman : Human() {
    override var color: String = "黃皮膚"
    override var language: String = "中文"

    override fun eat() {
        println("中國人用筷子吃飯苦酱!")
    }
}

abstract class UsHuman : Human() {
    //美國人的膚色很多,這里也不能確定冕房,所以不實現(xiàn) color躏啰,將類聲明為抽象類
    //override var color: String = "白皮膚"
    override var language: String = "英語"

    override fun eat() {
        println("美國人用刀叉吃飯!")
    }
}


fun main() {
    val zhHuman = ZhHuman()
    println(zhHuman.color)    //黃皮膚
    println(zhHuman.language) //中文
    zhHuman.eat()             //中國人用筷子吃飯耙册!
    zhHuman.walk()            //人類都是用雙腳走路!

    //val usHuman = UsHuman() //編譯錯誤毫捣,抽象類不能實例化
}

7详拙、接口

/**
 * 1、接口的定義和特點
 * (1)接口反映的是事物的能力
 * (2)使用 interface 來定義接口
 * (3)接口不能實例化蔓同,即不能創(chuàng)建接口對象
 * (4)kotlin 接口里面的字段不能實現(xiàn)(java 里面可以實現(xiàn))
 * (5)kotlin 接口里面的方法可以實現(xiàn)(java 里面不能實現(xiàn))
 */
//騎自行車
interface RideBike {
    fun ride()
}

//開車
interface DriveCar {
    var license: String //駕照號碼
    fun drive() {
        println("掛擋 -> 踩油門 -> 走你")
    }
}


/**
 * 2饶辙、接口的實現(xiàn)
 * (1)接口也可以繼承接口,添加新的能力
 * (2)一個類可以實現(xiàn)多個接口斑粱,用逗號隔開
 * (3)實現(xiàn)接口必須實現(xiàn)接口定義的所有未實現(xiàn)的方法和屬性
 */
//開船
interface Sail : DriveCar {
    fun course() //航向
}

class XiaoMing : RideBike, Sail {

    //小明的駕照號碼是123456789
    override var license: String = "123456789"

    override fun ride() {
        println("小明學會了騎自行車弃揽!")
    }

    override fun course() {
        println("一路向北!")
    }
}


fun main() {
    val xiaoMing = XiaoMing()
    xiaoMing.ride()   //小明學會了騎自行車则北!
    xiaoMing.drive()  //掛擋 -> 踩油門 -> 走你
    xiaoMing.course() //一路向北矿微!
    println(xiaoMing.license) //123456789
}

8、多態(tài)

/**
 * 1.多態(tài)
 * (1)多態(tài)即同一類對象對同一種功能具有不同的表現(xiàn)形式
 * (2)方法重寫:指向父類的對象調(diào)用此方法尚揣,其實執(zhí)行的是子類重寫的方法
 * (2)方法重載:由于父類沒有此方法涌矢,故指向父類的對象不能調(diào)用此方法
 */
open class Animal {
    open fun call() {
        println("動物叫聲")
    }
}

class Cat : Animal() {
    override fun call() {
        println("貓喵喵叫")
    }
}

class Duck : Animal() {
    fun call(isBig: Boolean) {
        println("鴨子呱呱叫")
    }
}

fun main() {
    val animal1: Animal = Cat()
    val animal2: Animal = Duck()
    animal1.call() //執(zhí)行的是子類重寫的方法,輸出:貓喵喵叫
    animal2.call() //子類沒有重寫快骗,執(zhí)行的是父類的方法娜庇,輸出:動物叫聲
    //animal2.call(true) //編譯失敗,Animal沒有這個方法方篮,故不能調(diào)用
}

9名秀、智能類型轉(zhuǎn)換

/**
 * 1、is 關(guān)鍵字:用來判斷某個對象是否是某個具體的類型
 * 2藕溅、as 關(guān)鍵字:用來將某個對象強轉(zhuǎn)成某個類型匕得,如果類型轉(zhuǎn)換錯誤會拋出 ClassCastException
 * 3、智能類型轉(zhuǎn)換:用is判斷之后就不需要再用 as 顯示轉(zhuǎn)換蜈垮,編譯器會自動轉(zhuǎn)換
 */
open class Canine

class ShepHerdDog : Canine() {
    fun herdShep() {
        println("牧羊犬放羊")
    }
}

class RuralDog : Canine() {
    fun watchDoor() {
        println("中華田園犬看家")
    }
}

fun main() {
    val canine1: Canine = ShepHerdDog()
    val canine2: Canine = RuralDog()

    if(canine1 is ShepHerdDog){
        //is判斷了耗跛,就不需要再用as顯示轉(zhuǎn)換
        //val shepHerdDog = canine1 as ShepHerdDog
        canine1.herdShep() //牧羊犬放羊
    }

    if(canine2 is RuralDog){
        canine2.watchDoor() //中華田園犬看家
    }

    //如果類型轉(zhuǎn)換錯誤會拋出ClassCastException
    val shepHerdDog = canine1 as ShepHerdDog
    shepHerdDog.herdShep() //牧羊犬放羊
    val ruralDog = canine2 as RuralDog
    ruralDog.watchDoor()   //中華田園犬看家
}

10、嵌套類

/**
 * 1攒发、嵌套類
 * (1)嵌套類是靜態(tài)類
 * (2)嵌套類和外部類沒有關(guān)系调塌,不能訪問外部類的成員
 * (3)嵌套類可以直接通過構(gòu)造函數(shù)創(chuàng)建對象
 */
class OutClass {
    var content = "嵌套類"

    class NestedClass {
        fun sayHello() {
            //println("hello $content") //編譯失敗
            println("Hello 嵌套類")
        }
    }
}

/**
 * 2、內(nèi)部類
 * (1)內(nèi)部類用關(guān)鍵字 inner 聲明
 * (2)內(nèi)部類是普通類
 * (3)可以把它看成是外部類的一個成員惠猿,它可以訪問外部類的成員
 * (4)內(nèi)部類的對象必須要通過外部類的對象來創(chuàng)建
 * (5)內(nèi)部類訪問外部類的同名成員需要使用 this@OutClass2 的形式調(diào)用
 */
class OutClass2 {
    var content = "外部類"

    inner class InnerClass {
        var content = "內(nèi)部類"
        fun sayHello1() {
            println("Hello $content")

        }

        fun sayHello2() {
            println("Hello ${this@OutClass2.content}")
        }
    }
}


fun main() {
    val nestedClass = OutClass.NestedClass()
    nestedClass.sayHello() //Hello 嵌套類

    val innerClass = OutClass2().InnerClass()
    innerClass.sayHello1() //Hello 內(nèi)部類
    innerClass.sayHello2() //Hello 外部類
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載羔砾,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市姜凄,隨后出現(xiàn)的幾起案子政溃,更是在濱河造成了極大的恐慌,老刑警劉巖态秧,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件董虱,死亡現(xiàn)場離奇詭異,居然都是意外死亡申鱼,警方通過查閱死者的電腦和手機愤诱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捐友,“玉大人淫半,你說我怎么就攤上這事∠蛔” “怎么了科吭?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長猴鲫。 經(jīng)常有香客問我对人,道長,這世上最難降的妖魔是什么变隔? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任规伐,我火速辦了婚禮,結(jié)果婚禮上匣缘,老公的妹妹穿的比我還像新娘猖闪。我一直安慰自己,他們只是感情好肌厨,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布培慌。 她就那樣靜靜地躺著,像睡著了一般柑爸。 火紅的嫁衣襯著肌膚如雪吵护。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天表鳍,我揣著相機與錄音馅而,去河邊找鬼。 笑死譬圣,一個胖子當著我的面吹牛瓮恭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播厘熟,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼屯蹦,長吁一口氣:“原來是場噩夢啊……” “哼维哈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起登澜,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤阔挠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后脑蠕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體购撼,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年谴仙,在試婚紗的時候發(fā)現(xiàn)自己被綠了份招。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡狞甚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出廓旬,到底是詐尸還是另有隱情哼审,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布孕豹,位于F島的核電站涩盾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏励背。R本人自食惡果不足惜春霍,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叶眉。 院中可真熱鬧址儒,春花似錦、人聲如沸衅疙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饱溢。三九已至喧伞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绩郎,已是汗流浹背潘鲫。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肋杖,地道東北人溉仑。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像兽愤,于是被迫代替她去往敵國和親彼念。 傳聞我的和親對象是個殘疾皇子挪圾,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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