Kotlin面向对象

面向对象

至于什么是面向对象编程,我就不多扯了,大概就是下面这样…
在这里插入图片描述
咳咳抖个机灵,类是对事物的一种封装啊,封装继承和多态是面向对象的三大特征啊啥的这些都被说烂了的。

  • 封装

我们直接开始在Kotlin中建立一个类,叫Person:

class Person {
    var name = ""
    var age = 0

    fun eat() {
        println("$name is eating. He is  $age years old.")
    }
}

接下来开始实例化这个Person类:

val person = Person()

Kotlin中实例化类和JAVA差不多,去掉了new关键字

之所以这么设计,是因为当你调用了某个类的构造函数时,你的意图只可能是对这个类进行实例化,因此即使没有new关键字,也能清晰表达出你的意图,Kotlin本着最简化的设计原则,将诸如new、行尾分号这种不必要的语法结构都取消了

接下来我们对person对象进行一系列操作:

val person = Person()
person.name = "Koma"
person.age = 25
person.eat()

可以看到,Kotlin默认对var的变量添加了get和set方法,而val由于是不可变的,只有get方法。运行之后可以看到控制台打印出了Koma is eating. He is 25 years old.日志。

  • 继承

在Kotlin中,要继承一个类需要做的第一件事就是:使这个类可以被继承
纳尼????类不是直接继承的吗?还需要让它可以被继承???对于写惯了JAVA的人来说可能要发出一声惊叹,事实上,在Kotlin中任何一个非抽象类默认都是不可被继承的,相当于JAVA类加了final关键字修饰。

之所以这么设计,其实和val关键字的原因是差不多的,因为类和变量一样,最好都是不可变的,而一个类允许被继承的话,它无法预知子类会如何实现,因此可能就会存在一些未知的风险,Effective Java这本书中明确提到,如果一个类不是专门为继承而设计的,那么就应该主动将它加上final声明,禁止它可以被继承

很简单,在类前面加上open关键字就可以了:
open class Person

然后新定义一个Student类继承Person类:

class Student : Person(){
}

可以看到除了把extend关键字换成冒号之外,类名后面竟然加了括号!
因为这涉及到Kotlin的主构造函数和次构造函数
主构造函数将会是我们最常用的构造函数,每个类默认都会有一个无参构造函数,当然你也可以显示的给它指定参数:

class Student(val grade: Int) : Person(){
}

那么这个时候要实例化Student类的话,就要传参了:

val student = Student(100)

因为构造函数中的参数实在创建对象的时候就传入了,所以直接定义为val就可以。
我们以前在JAVA的有参构造函数中可以处理一些逻辑,Kotlin提供了一个init结构体,所有主构造函数中的逻辑都可以写在里面

 init {
        println("grade is $grade")
    }

因为JAVA规定了子类的构造函数中必须调用分类的构造函数,这个规定Kotlin也要遵守。

由于我们在定义Student的时候没有构造函数的函数体,所以可以写在init结构体里面,但是这不是一个好主意,因为绝大多数时候我们是不需要去写init结构体的。

所以Kotlin采用了括号这种方式,子类在继承的时候想调用父类的哪个构造函数,直接通过括号来指定,这里我们写了空括号,就代表我们要调用Person的无参构造方法
如果定义Person类的时候给它指定了参数:

class Person(val name: String, bal age: Int){}

那么此时Person已经没有无参构造方法了,上面Student继承Person的时候就会报错,这个时候必须传给Person两个参数:

class Student : Person("Koma",100) {}

次构造函数我懒得说了,基本用不到。

  • 接口

接口是实现多态的重要组成部分,在JAVA里,继承只能是单继承,Kotlin也是一样。虽然只能继承一个父类,但是可以实现多个接口。
接口就是对一些列行为进行抽象,然后由具体的类去实现,具体为:

interface Study {
    fun readBooks()
    fun doHomework()
}

定义一个Study接口,然后让Student类去实现:

class Student(val name: String) : Study {

    override fun readBooks() {
        println("$name is reading")
    }

    override fun doHomework() {
        println("$name is doing homework")
    }
}

JAVA中继承一个类要用extend关键字,实现接口使用implements关键字,而Kotlin统一使用冒号,可以看到Study后面并没有括号,因为接口没有构造函数可以来调用。Kotlin中使用override关键字来重写父类或者接口中的函数。

  • 多态
    接下来演示一下Kotlin中的多态编程:
fun main() {
    val student = Student("Koma")
    doStudy(student)
}

fun doStudy(study: Study) {
    study.readBooks()
    study.doHomework()
}

定义一个doStudy函数,其参数要求是Study类型的,Study是我们刚刚定义的接口,但因为我们Student类实现了Study接口,所以在doStudy函数中可以直接将student传进来 ,这个时候student就向上转型了。

还有一个重要的地方,就是Kotlin支持对接口中定义的方法添加 默认实现。其实Java在JDK1.8之后也加入这个功能了。在Kotlin中的具体表现为:

interface Study {
    
    fun readBooks()

    fun doHomework() {
        println("没有人实现我,这是Study接口自己的实现")
    }
}

刚刚的Study接口中,直接在doHomework后面跟上方法体就好了,当一个接口里的方法有了默认实现,那么Student类在实现Study接口的时候就可以自由选择是否实现doHomework方法了,如果不实现的话,调用的时候就执行的是默认实现方法:

class Student(val name: String) : Study {

    override fun readBooks() {
        println("$name is reading")
    }
}

fun main() {
    val student = Student("Koma")
    doStudy(student)
}

fun doStudy(study: Study) {
    study.readBooks()
    study.doHomework()
}

在这里插入图片描述

  • 访问修饰符
    Java中有public、private、protected和default(什么都不写)这4中访问修饰符,Kotlin也有4种:public、private、protected和internal

private:和Java的一样,都表示只对当前类内部可见。

public:和Java中的一样。但是Kotlin中的默认项是public,而Java的默认是default。

protected:Java中表示对当前类、子类和同一包路径下的类可见 ,在Kotlin中只对当前类和子类可见。

interval:只对同一模块中的类可见比如我们开发了一个模块给别人使用,但是有一些函数只想在我们的模块内部中去调用,这个时候就要用上internal来修饰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值