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 外部類
}
/**
* 任何復雜的數(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()
}
/**
* 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
}
/**
* 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=騰訊]
}
/**
* 所謂封裝就是隱藏內(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() //放水 -> 開始洗衣服 -> 脫水烘干 -> 衣服洗好了
}
/**
* 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 屬性不能重寫
}
/**
* 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() //編譯錯誤毫捣,抽象類不能實例化
}
/**
* 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
}
/**
* 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)用
}
/**
* 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() //中華田園犬看家
}
/**
* 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 外部類
}