Kotlin 简明教程
Kotlin - Inheritance
继承可以定义为一个类获取另一个类的成员(方法和属性)的过程。通过使用 inheritance ,信息以分层顺序变得可管理。
继承其他类成员的类称为 subclass (派生类或子类),而成员被继承的类称为 superclass (基类或父类)。
继承是面向对象编程的主要特征之一,它允许用户基于现有类创建新类。继承我们可以从基类继承所有特性,并且还可以拥有自己的其他特性。
Kotlin 中的所有类都有一个名为 Any 的共同超类,这是没有声明父类的类的默认超类:
class Example // Implicitly inherits from Any
Kotlin 超类 Any 有三个方法: equals() 、 hashCode() 和 toString() 。因此,这些方法已为所有 Kotlin 类定义。
在 Kotlin 中,所有内容默认情况下都是 final ,因此,我们需要在类声明前使用关键字 open 使其他类可以继承它。Kotlin 使用运算符 ":" 来继承类。
Example:
看一下下面的继承示例。
open class ABC {
fun think () {
println("Hey!! i am thiking ")
}
}
class BCD: ABC(){ // inheritence happend using default constructor
}
fun main(args: Array<String>) {
var a = BCD()
a.think()
}
当你运行上述 Kotlin 程序时,它将生成以下输出:
Hey!! i am thiking
Overriding Methods
现在,如果我们希望在子类中 override think() 方法。然后,我们需要考虑以下示例,其中我们创建两个类并将其中一个函数覆盖到子类中。
open class ABC {
open fun think () {
println("Hey!! i am thinking ")
}
}
class BCD: ABC() { // inheritance happens using default constructor
override fun think() {
println("I am from Child")
}
}
fun main(args: Array<String>) {
var a = BCD()
a.think()
}
当你运行上述 Kotlin 程序时,它将生成以下输出:
I am from Child
用关键字 override 标记的成员本身是 open ,因此可以在子类中覆盖它。如果您想禁止重新覆盖它,那么您必须将其 final 如下所示:
class BCD: ABC() {
final override fun think() {
println("I am from Child")
}
}
Overriding Properties
覆盖机制对属性的工作方式与对方法的工作方式相同。在超类中声明的属性(然后在派生类中重新声明)必须以关键字 override 为前缀,并且它们必须具有兼容的类型。
open class ABC {
open val count: Int = 0
open fun think () {
println("Hey!! i am thinking ")
}
}
class BCD: ABC() {
override val count: Int
init{
count = 100
}
override fun think() {
println("I am from Child")
}
fun displayCount(){
println("Count value is $count")
}
}
fun main(args: Array<String>) {
var a = BCD()
a.displayCount()
}
当你运行上述 Kotlin 程序时,它将生成以下输出:
Count value is 100
我们还可以在主构造函数中将 override 关键字用作属性声明的一部分。以下示例使用主构造函数来覆盖 count 属性,如果没有将任何值传递给构造函数,它将使用 400 作为默认值:
open class ABC {
open val count: Int = 0
open fun think () {
println("Hey!! i am thinking ")
}
}
class BCD(override val count: Int = 400): ABC() {
override fun think() {
println("I am from Child")
}
fun displayCount(){
println("Count value is $count")
}
}
fun main(args: Array<String>) {
var a = BCD(200)
var b = BCD()
a.displayCount()
b.displayCount()
}
当你运行上述 Kotlin 程序时,它将生成以下输出:
Count value is 200
Count value is 400
Derived Class Initialization Order
当我们创建派生类的对象时,构造函数初始化从基类开始。这意味着首先会初始化基类属性,之后将调用任何派生类指令,并且同样适用于任何进一步派生类。
这意味着当执行基类构造函数时,在派生类中声明或覆盖的属性尚未初始化。
open class Base {
init{
println("I am in Base class")
}
}
open class Child: Base() {
init{
println("I am in Child class")
}
}
class GrandChild: Child() {
init{
println("I am in Grand Child class")
}
}
fun main(args: Array<String>) {
var a = GrandChild()
}
当你运行上述 Kotlin 程序时,它将生成以下输出:
I am in Base class
I am in Child class
I am in Grand Child class
Access Super Class Members
派生类中的代码可以使用 super 关键字直接调用其超类的函数和属性:
open class Base() {
open val name:String
init{
name = "Base"
}
open fun displayName(){
println("I am in " + this.name)
}
}
class Child(): Base() {
override fun displayName(){
super.displayName()
println("I am in " + super.name)
}
}
fun main(args: Array<String>) {
var a = Child()
a.displayName()
}
当你运行上述 Kotlin 程序时,它将生成以下输出:
I am in Base
I am in Base
Overriding rules
如果子类从其直接超类继承同一成员的多个实现,则它必须覆盖此成员并提供其自己的实现。
这与从单个父类中继承成员的子类不同,在这种情况下,子类不必提供所有开放成员的实现。
open class Rectangle {
open fun draw() { /* ... */ }
}
interface Polygon {
fun draw() { /* ... */ } // interface members are 'open' by default
}
class Square() : Rectangle(), Polygon {
// The compiler requires draw() to be overridden:
override fun draw() {
super<Rectangle>.draw() // call to Rectangle.draw()
super<Polygon>.draw() // call to Polygon.draw()
}
}
从 Rectangle 和 Polygon 中继承是正常的,但它们都有各自的 draw() 方法的实现,因此您需要覆盖 Square 中的 draw() 并提供单独的实现来消除歧义。