超类(Any)

Kotlin 中所有类都继承该 Any 类,它是所有类的超类,对于没有超类型声明的类是默认超类:

class Example // 从 Any 隐式继承

 如果一个类要被继承,可以使用 open 关键字进行修饰。

open class Base(p: Int)           // 定义基类

class Derived(p: Int) : Base(p)

定义

  • 定义继承类的关键字为:open。不管是类、还是成员都需要使用open关键字。
  • 定义格式为:
open class 类名{
...
open var/val 属性名 = 属性值
...
open fun 函数名()
...
}

 例:这里定义一个继承类Demo,并实现两个属性与方法,并且定义一个DemoTest去继承自Demo

open class Demo{

open var num = 3

open fun foo() = "foo"

open fun bar() = "bar"

}

class DemoTest : Demo(){
// 这里值得注意的是:Kotlin使用继承是使用`:`符号,而Java是使用extends关键字
}

fun main(args: Array<String>) {

println(DemoTest().num)
DemoTest().foo()
DemoTest().bar()

}

//输出结果为:
//3
//foo
//bar

继承类的构造函数

  • 无主构造函数

当实现类无主构造函数时,则每个辅助构造函数必须使用super关键字初始化基类型,或者委托给另一个构造函数。 请注意,在这种情况下,不同的辅助构造函数可以调用基类型的不同构造函数
例:这里举例在Android中常见的自定义View实现,我们熟知,当我们指定一个组件是,一般实现继承类(基类型)的三个构造函数。

class MyView : View(){

constructor(context: Context) : super(context)

constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
: super(context, attrs, defStyleAttr)
}

可以看出,当实现类无主构造函数时,分别使用了super()去实现了基类的三个构造函数。

  • 存在主构造函数

当存在主构造函数时,主构造函数一般实现基类型中参数最多的构造函数,参数少的构造函数则用this关键字引用即可了

class MyView(context: Context?, attrs: AttributeSet?, defStyleAttr: Int)
: View(context, attrs, defStyleAttr) {

constructor(context: Context?) : this(context,null,0)

constructor(context: Context?,attrs: AttributeSet?) : this(context,attrs,0)
}

 Kotlin 中的重写

  • 函数重写

基类中,使用fun声明函数时,此函数默认为final修饰,不能被子类重写。如果允许子类重写该函数,那么就要手动添加 open 修饰它, 子类重写方法使用 override 关键词:

/**用户基类**/
open class Person{
open fun study(){ // 允许子类重写
println("我毕业了")
}
}

/**子类继承 Person 类**/
class Student : Person() {

override fun study(){ // 重写方法
println("我在读大学")
}
}
//输出结果为:
//我在读大学

fun main(args: Array<String>) {
val s = Student()
s.study();
}

 如果有多个相同的方法(继承或者实现自其他类,如A、B类),则必须要重写该方法,使用super范型去选择性地调用父类的实现。

open class A {
open fun f () { print("A") }
fun a() { print("a") }
}

interface B {
fun f() { print("B") } //接口的成员变量默认是 open 的
fun b() { print("b") }
}

class C() : A() , B{
override fun f() {
super<A>.f()//调用 A.f()
super<B>.f()//调用 B.f()
}
}

fun main(args: Array<String>) {
val c = C()
c.f();

}

//输出结果为:
//AB

C 继承自 a() 或 b(), C 不仅可以从 A 或则 B 中继承函数,而且 C 可以继承 A()、B() 中共有的函数。此时该函数在中只有一个实现,为了消除歧义,该函数必须调用A()和B()中该函数的实现,并提供自己的实现。 

  • 属性重写

属性重写使用 override 关键字,属性必须具有兼容类型,每一个声明的属性都可以通过初始化程序或者getter方法被重写:

open class Foo {
open val x: Int get { …… }
}

class Bar1 : Foo() {
override val x: Int = ……
}

你可以用一个var属性重写一个val属性,但是反过来不行。因为val属性本身定义了getter方法,重写为var属性会在衍生类中额外声明一个setter方法 

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

interface Foo {
val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
override var count: Int = 0
}