文章目录

面向对象

fun main(args: Array<String>) {
var rect01 = Rect(20,10)
println("矩形的宽度:"+rect01.width+",矩形的高度:"+rect01.height)
}

class Rect(var width:Int,var height:Int)

【kotlin】面向对象、封装、继承、多态_kotlin

fun main(args: Array<String>) {
var rect01 = Rect(20,10)
rect01.area()
rect01.circu()
}

class Rect(var width:Int,var height:Int){
fun area(){
println("矩形的面积:"+width*height)
}
fun circu(){
println("矩形的周长::"+(width+height)*2)
}
}

【kotlin】面向对象、封装、继承、多态_ide_02
静态行为,动态方法
这里静态的是这个长方形的属性,长和宽
这里动态的是这个长方形的方法,获取面积和获取周长的方法

封装

【kotlin】面向对象、封装、继承、多态_父类_03
我们再来举个栗子,洗衣机的栗子

新建一个class文件WashMachine

class WashMachine(var module:String,var size:Int) {
var isDoorOpen = true
var currentMode = 0

fun openDoor(){
println("洗衣机的门打开了")
isDoorOpen = true
}
fun closeDoor(){
println("洗衣机的门关闭了")
isDoorOpen = false
}
fun selectMode(mode:Int){
currentMode = mode
when(mode){
0 -> println("初始模式,请选择模式")
1 -> println("消毒洗")
2 -> println("棉麻洗")
else -> println("进入了奇怪模式")
}
}
fun start(){
if(isDoorOpen){
println("嘀嘀嘀门还没关,不能运行")
}else{
when(currentMode){
0 -> {println("选择模式错误,不能运行")}
1 -> {
println("进入消毒洗,高温")
setMotorSpeed(100)
}
2 -> {
println("进入棉麻洗,轻柔")
setMotorSpeed(200)
}
}
println("洗衣服开始")
}

}

//私有,只有这个类中能调用
private fun setMotorSpeed(speed:Int){
println("当前发动机转速${speed}圈/秒")
}
}
fun main(args: Array<String>) {
var washMachine = WashMachine("小天鹅",12);
washMachine.openDoor()
washMachine.closeDoor()
washMachine.selectMode(1)
washMachine.start()
}

【kotlin】面向对象、封装、继承、多态_ide_04

继承

在 Kotlin 中任何一个非抽象类默认都是不可以被继承的(抽象类本身无法创建实例,一定要由子类继承它才能创建实例),相当于给 Java 中给类声明了 final,好的编程习惯是如果一个类不是专门为继承而设计的,那么就应该主动将它加上 ​​final​​声明,禁止它可以被继承

新建一个Father类,如果想被继承需要加​​open​​关键字

open class Father {
var character:String = "性格外向"
fun action(){
println("喜欢在公共场合唱歌");
}
}

新建一个Son类继承Father类,可以发现 Father 后有一对括号,这就涉及到 Java 继承特性中的一个规定:子类总的构造函数必须调用父类中的构造函数,这个规定 Kotlin 中也要遵守。子类中的主构造函数调用父类中的哪个构造函数,在继承的时候通过括号来指定

Father 类后一对空括号表示 Son 类的主构造函数在初始化的时候会调用 Father 类的无参构造函数,即使在无参数情况下,括号也不能省略

class Son : Father() {
}

测试下

fun main(args: Array<String>) {
var son = Son()
println(son.character)
son.action()
}

查看运行结果
【kotlin】面向对象、封装、继承、多态_kotlin_05
我们来试下重写父类方法

class Son : Father() {
override fun action(){
println("喜欢在公共场合跳舞")
}
}

查看执行结果
【kotlin】面向对象、封装、继承、多态_父类_06

多态

【kotlin】面向对象、封装、继承、多态_父类_07
创建一个抽象的人类

/*
* 抽象的人类
*/
abstract class Human(var name:String) {
abstract fun eat()
}

创建男人类

class Man(name:String):Human(name) {
override fun eat(){
println("${name}喜欢吃鸡腿")
}
}

创建女人类

class Woman(name:String):Human(name) {
override fun eat(){
println("${name}喜欢吃鸭脖")
}
}

编写测试代码

fun main(args: Array<String>) {
var man = Man("赵四")
man.eat()

var woman = Woman("李小花")
woman.eat()
}

查看测试结果
【kotlin】面向对象、封装、继承、多态_构造函数_08
我们给Human再增加一个方法love

/*
* 抽象的人类
*/
abstract class Human(var name:String) {
abstract fun eat()
abstract fun love()
}

Man和Woman都需要重写这个方法

class Man(name:String):Human(name) {
......
override fun love(){
println("${name}爱买游戏")
}
}

class Woman(name:String):Human(name) {
......
override fun love(){
println("${name}爱买面膜")
}
}

编写测试代码

fun main(args: Array<String>) {
var man1 = Man("赵四")
var woman1 = Woman("李小花")
var man2 = Man("刘能")
var woman2 = Woman("王大花")

var humanList = listOf<Human>(man1,woman1,man2,woman2)
for(h in humanList){
h.love()
}
}

查看运行结果
【kotlin】面向对象、封装、继承、多态_kotlin_09

主构造函数和次构造函数

Kotlin 将构造函数分成了两种:主构造函数和次构造函数
每个类都默认有一个不带参数的主构造函数,当然你也可以显式地给它指明参数。主构造函数特点是没有函数体,直接定义在类名后面即可。例如上面的洗衣机类 WashMachine 就将两个字段放到了主构造函数中了

由于构造函数中的参数是在创建实例的时候传入的,因此我们可以将参数声明成 ​​val​

Kotlin 为我们提供了一个 ​​init​​​ 结构体,所有主函数中的逻辑都可以写在这里,绝大多数情况下我们不需要写 ​​init​​ 结构体的

class WashMachine(var module:String,var size:Int) {
var isDoorOpen = true
var currentMode = 0

init{
println("module:"+module)
print("size:"+size)
}
......
}

如果 将 Father 类改造下

open class Father(character:String,like:String) {
...
}

那么 Son 类一定会报错,以为要给 Father 传入两个参数,而 Son 类中没有,所以得增加如下

class Son(character:String,like:String) : Father(character,like) {
}

在 Son 类主构造函数增加 character 和 like 时,不能声明成 ​​val​​​ ,因为在主构造函数中声明成 ​​val​​​ 或 ​​var​​ 的参数将自动成为该类的字段,会导致和父类同名字段冲突

任何一个类只能有一个主构造函数,但可以有多个次构造函数,次构造函数通过​​constructor​​来定义。Kotlin 规定当一个类既有主构造函数,又有次构造函数时,所有次构造函数必须调用主构造函数(包括间接调用)

class Son(character:String,like:String) : Father(character,like) {
constructor(character: String):this("","")
constructor():this("")
}

于是我们有3种方式对 Son 实例化

val son1 = Son();
val son2 = Son("性格内向");
val son3 = Son("性格内向","喜欢运动");

还有一种非常特殊的情况:类中只有次构造函数,没有主构造函数。当一个类中没有显式地定义主构造函数且定义了次构造函数,它就是没有主构造函数的

class Son: Father{
constructor(character: String,like:String):super(character,like)
}

Son 是没有主构造函数的,继承 Father 类时也就不需要加括号了。由于没有主构造函数,次构造函数只能调用父类的构造函数,所以用了 super 关键字