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

提示:本文为作者阅读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

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.f()
        super.f()
    }

}

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

//抽象类
abstract class G{
    abstract fun g()//抽象方法
}

class H: G() {
    override fun g() {
        TODO("not implemented")
    }
}

你可能感兴趣的:(android,kotlin,类,继承,Kotlin学习笔记)