Kotlin学习笔记(三)类和继承

来源:互联网 发布:宁静长相 知乎 编辑:程序博客网 时间:2024/06/09 23:58

提示:本文为作者阅读Kotlin中文站学习笔记,建议读者移步Kotlin中文站完整学习。

Kotlin中,使用class关键字生命一个类。类声明由类名,类头(指定其类型参数,主构造函数等)和大括号括起来的类体组成。

class A public constructor(arg1:String){}

Kotlin中,一个类可以有一个主构造函数或和一个或多个次构造函数。主构造函数是类头的一部分,跟在类名(和可选的类型参数)后面,如果主构造函数没有任何注解或可见性修饰符,可以省略constructor关键字。

class A (arg1:String){}

主构造函数不包含任何的代码,初始化代码可以放到init关键字修饰的初始化块中:

class A (arg1:String){    //初始化块    init {        //...    }}

主构造函数中的参数可以在初始化块,或类体内声明的属性初始化器中使用:

class(arg1:String){    var s tr:String=arg1    //初始化块    init {        print(arg1)    }}

也可以以下方式,声明属性及在主构造函数中初始化属性:

class A (var arg1:String){}

类也可以声明前缀有constructor的次构造函数,如果类有主构造函数,每个次构造函数都要委托给主构造函数,可以直接委托,也可以通过别的次构造函数间接委托。委托到同一个类中的另一个构造函数,用this关键字即可。

class A (var arg1:String){constructor():this("")//次构造函数}

如果一个非抽象类没有声明任何(主,次)构造函数,Kotlin会生成一个不带任何参数的默认构造函数,可见性为public。

在 JVM 上,如果主构造函数的所有的参数都有默认值,编译器会生成 一个额外的无参构造函数,它将使用默认值。

class A (var arg1:String=""){}

在Kotlin中,没有new关键字,要创建一个类的实例,只需像调用普通函数一样,调用类的构造函数:

var a:A=A()//创建一个A的实例 

继承

Kotlin中所有的类都有一个共同的超累类Any,对于没有超类型声明的类是默认超类。Any类不是java.lang.Object类,它只有equals,hashCode(),toString()3个成员方法。

要显式声明一个超类,可以把类型放到类头的冒号之后,如果该基类有一个主构造函数,则其基类必须用主构造函数的参数就地初始化:

class B constructor(arg: String):A(arg){}

如果类没有主构造函数,那么每个次构造函数必须使用 super 关键字初始化其基类型,或委托给另一个构造函数做到这一点。 注意,在这种情况下,不同的次构造函数可以调用基类型的不同的构造函数:

class MyView : View {    constructor(ctx: Context) : super(ctx)    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)}

类上的 open 标注与 Java 中 final 相反,它允许其他类从这个类继承。默认情况下,在 Kotlin 中所有的类都是 final。

Kotlin力求清晰,需要显式标注可以覆盖的成员及覆盖后的成员。

open class A constructor(arg1:String){    open fun f():Unit{    }}class B :A(){    override fun f() {        super.f()    }}

B.f()函数必须加上override标注,否则会编译出错。如果A.f()没有加open标注,则子类中不允许定义相同签名的函数,不论加不加override。在一个final类(没有open标注的类),开放成员是禁止的。Kotlin中默认类是final的。
标记为override的成员本身是开放的,可以在子类中覆盖。如果你想禁止其在子类中继续被覆盖,可以加final关键字。

class B :A(){    final override fun f() {        super.f()    }}

属性覆盖与方法覆盖类似,在超类中声明然后在派生类中重新声明的属性必须以override开头,并且必须具有兼容的类型。每个声明的属性可以由具有初始化器的属性或getter方法的属性覆盖。

open class C {    open val str: String get() = "Hello World!"}class D : C() {    override var str: String        get() = super.str        set(value) {            str = value        }}

我们可以用一个 var 属性覆盖一个 val 属性,但反之则不行。这是允许的,因为一个 val 属性本质上声明了一个 getter 方法,而将其覆盖为 var 只是在子类中额外声明一个 setter 方法。

我们也可以在主构造函数中使用 override 关键字作为属性声明的一部分。

open class C {    open val str: String get() = "Hello World!"}class D constructor(override val str: String): C() {}

在 Kotlin 中,实现继承由下述规则规定:如果一个类从它的直接超类继承相同成员的多个实现, 它必须覆盖这个成员并提供其自己的实现(也许用继承来的其中之一)。 为了表示采用从哪个超类型继承的实现,我们使用由尖括号中超类型名限定的 super,如super<E>

interface E{    fun f():Unit{        print("f in E")    }}interface F{    fun f():Unit{        print("f in F")    }}class D:E,F{    override fun f() {        super<E>.f()        super<F>.f()    }}

我们可以用abstract关键字定义抽象类和抽象方法,抽象方法不需要在本类实现,并且不需要用open关键字标注一个抽象类或抽象方法-因为这不言而喻。

//抽象类abstract class G{    abstract fun g()//抽象方法}class H: G() {    override fun g() {        TODO("not implemented")    }}
原创粉丝点击