Kotlin - 继承

Kotlin - 继承 首页 / Kotlin入门教程 / Kotlin - 继承

继承是面向对象编程语言的重要函数。继承允许将现有类(或基类或父类)的函数继承到新类(或派生类或子类)。

主类称为超类(或父类),而继承超类的类称为子类。子类包含超类及其自身的函数。

当两个或多个类具有相同的属性时,就可以使用继承的概念。它允许代码可重用。派生类仅具有一个基类,但可以具有多个接口,而基类可以具有一个或多个派生类。

在Kotlin中,派生类使用类标题中的:运算符继承基类。

open class Base(p: Int){

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

}

假设无涯教程有两个不同的类“ Programmer”和“ Salesman”,它们具有共同的属性“ name”,“ age”和“ salary”,以及它们各自独立的函数doProgram()和fieldWork()。继承函数使无涯教程可以继承(Employee)包含通用函数。

open class Employee(name: String, age: Int, salary: Float) {
   //code of employee
}

class Programmer(name: String, age: Int, salary: Float): Employee(name,age,salary) {
   //code of programmer
}

class Salesman(name: String, age: Int, salary: Float): Employee(name,age,salary) {
   //code of salesman
}

所有Kotlin类都有一个公共的超类“ Any”。它是没有明确指定超类的类的默认超类。

例如,类Example隐式继承自Any。

class Example

Open关键字

由于Kotlin类默认为final类,因此不能简单地继承它们。无涯教程在类之前使用open关键字来继承一个类并将其设置为非最终形式,

例如:

open class Example{
// 我现在可以扩展了!
}

从类继承字段

当无涯教程继承一个类以派生类时,所有字段和函数都会被继承。无涯教程可以在派生类中使用这些字段和函数。

例如:

open class Base{
  val x = 10
}
class Derived: Base() {
    fun foo() {
      println("x is equal to " + x)
    }
}
fun main(args: Array<String>) {
    val derived = Derived()
    derived.foo() 
}

输出:

x is equal to 10

从类继承方法

open class Bird {
    fun fly() {
      println("flying...")
    }
}
class Duck: Bird() {
    fun swim() {
      println("swimming...")
    }
}
fun main(args: Array<String>) {
    val duck = Duck()
    duck.fly() 
    duck.swim()
}

输出:

flying...
swimming...

继承示例

在这里,无涯教程声明一个类Employee为超类,而Programmer和Salesman是其子类。子类继承属性name,age和salary,并且子类包含其自己的函数,例如doProgram()和fieldWork()。

无涯教程网

open class Employee(name: String, age: Int, salary: Float) {
  init {
    println("Name is $name.")
    println("Age is $age")
    println("Salary is $salary")
 }
}
class Programmer(name: String, age: Int, salary: Float):Employee(name,age,salary){
    fun doProgram() {
      println("programming is my passion.")
    }
}
class Salesman(name: String, age: Int, salary: Float):Employee(name,age,salary){
    fun fieldWork() {
      println("travelling is my Learnfk.")
    }
}
fun main(args: Array<String>){
    val obj1 = Programmer("Ashu", 25, 40000f)
    obj1.doProgram()
    val obj2 = Salesman("Ajay", 24, 30000f)
    obj2.fieldWork()
}

输出:

Name is Ashu.
Age is 25
Salary is 40000.0
programming is my passion.
Name is Ajay.
Age is 24
Salary is 30000.0
travelling is my Learnfk.

继承和主构造函数

如果在这种情况下,基类和派生类都具有主构造函数,则在基类的主构造函数中初始化参数。在上面的继承示例中,所有类都包含三个参数“ name”,“ age”和“ salary”,并且所有这些参数都在基类的主构造函数中初始化。

当基类和派生类在其主构造函数中都包含不同数量的参数时,则从派生类对象初始化基类参数。

例如:

open class Employee(name: String,salary: Float) {
   init {
    println("Name is $name.")
    println("Salary is $salary")
   }
}
class Programmer(name: String, dept: String, salary: Float):Employee(name,salary){
    init {
      println("Name $name of department $dept with salary $salary.")
    }
    fun doProgram() {
      println("Programming is my passion.")

    }
}
class Salesman(name: String, dept: String, salary: Float):Employee(name,salary){
    init {
      println("Name $name of department $dept with salary $salary.")
    }
    fun fieldWork() {
      println("Travelling is my Learnfk.")

    }
}
fun main(args: Array<String>){
    val obj1 = Programmer("Ashu", "Development", 40000f)
    obj1.doProgram()
    println()
    val obj2 = Salesman("Ajay", "Marketing", 30000f)
    obj2.fieldWork()
}

输出:

Name is Ashu.
Salary is 40000.0
Name Ashu of department Development with salary 40000.0.
Programming is my passion.

Name is Ajay.
Salary is 30000.0
Name Ajay of department Marketing with salary 30000.0.
Travelling is my Learnfk.

创建派生类的对象时,它将首先调用其超类,并执行基类的init块,然后执行其自身的块。

继承和次构造函数

如果派生类不包含任何主构造函数,则需要使用super关键字从派生类调用基类的辅助构造函数。

例如

open class Patent {

    constructor(name: String, id: Int) {
      println("execute super constructor $name: $id")
    }
}

class Child: Patent {

    constructor(name: String, id: Int, dept: String): super(name, id) {
        print("execute child class constructor with property $name, $id, $dept")
    }
}
fun main(args: Array<String>) {
    val child = Child("Ashu",101, "Developer")
}

输出:

execute super constructor Ashu: 101
execute child class constructor with property Ashu, 101, Developer

在上面的示例中,创建Child类的对象时,它将调用其构造函数并使用值“ Ashu”,“ 101”和“ Developer”初始化其参数。同时,Child类构造函数使用具有name和id值的super关键字调用其超级类构造函数。由于存在super关键字,因此超类构造函数的主体首先执行,然后返回Child类构造函数。

方法覆盖

方法覆盖是指将父类(父类)的方法具体实现到其子类(子类)。

换句话说,当子类将其超类的方法重新定义或修改为子类时,称为方法重写。方法重写只能在继承中进行。

    继承而不覆盖

    open class Bird {
        open fun fly() {
          println("Bird is flying...")
        }
    }
    class Parrot: Bird() {
    
    }
    class Duck: Bird() {
    
    }
    fun main(args: Array<String>) {
        val p = Parrot()
        p.fly()
        val d = Duck()
        d.fly()
    }

    输出:

    Bird is flying...
    Bird is flying...
    

    在上面的示例中,没有覆盖基类方法的程序,无涯教程发现派生类Parrot和Duck都执行相同的通用操作。为了克服这个问题,无涯教程使用方法覆盖的概念。

    链接:https://www.learnfk.comhttps://www.learnfk.com/kotlin/kotlin-inheritance.html

    来源:LearnFk无涯教程网

    方法覆盖例子

    在此示例中,父类Bird的fly()方法在其子类Parrot和Duck中被覆盖。要覆盖父类的方法,必须将要覆盖的父类及其方法声明为open。同时,在子类中被覆盖的方法必须以关键字override作为开头。

    open class Bird {
        open fun fly() {
          println("Bird is flying...")
        }
    }
    class Parrot: Bird() {
        override fun fly() {
          println("Parrot is flying...")
        }
    }
    class Duck: Bird() {
        override fun fly() {
          println("Duck is flying...")
        }
    }
    fun main(args: Array<String>) {
        val p = Parrot()
        p.fly()
        val d = Duck()
        d.fly()
    }

    输出:

    Parrot is flying...
    Duck is flying...
    

    属性覆盖例子

    与方法类似,超类的属性也可以在其子类中被覆盖。 Bird类的color属性在其子类Parrot和Duck中被覆盖并进行了修改。

    open class Bird {
        open var color = "Black"
        open fun fly() {
          println("Bird is flying...")
        }
    }
    class Parrot: Bird() {
        override var color = "Green"
        override fun fly() {
          println("Parrot is flying...")
        }
    }
    class Duck: Bird() {
        override var color = "White"
        override fun fly() {
          println("Duck is flying...")
        }
    }
    fun main(args: Array<String>) {
        val p = Parrot()
        p.fly()
        println(p.color)
        val d = Duck()
        d.fly()
        println(d.color)
    }

    输出:

    Parrot is flying...
    Green
    Duck is flying...
    White
    

    无涯教程可以在继承中使用var属性覆盖val属性,但反之亦然。

    超类实现

    派生类也可以使用 super 关键字调用其超类方法和属性。

    例如:

    open class Bird {
        open var color = "Black"
        open fun fly() {
          println("Bird is flying...")
        }
    }
    class Parrot: Bird() {
        override var color = "Green"
        override fun fly() {
            super.fly()
            println("Parrot is flying...")
    
        }
    }
    
    fun main(args: Array<String>) {
        val p = Parrot()
        p.fly()
        println(p.color)
    
    }

    输出:

    Bird is flying...
    Parrot is flying...
    Green
    

    多类实现

    在Kotlin中,派生类在实现多个类中提供的相同函数名称时,在尖括号中使用超类名称,例如gsuper <Base>。

    例如,派生类Parrotextends继承其超类Bird,并实现包含相同函数fly()的Duck接口。要调用每个类和接口的特定方法,无涯教程必须在尖括号中提及每个类型的超类型名称,分别为super <Bird> .fly()和super <Duck> .fly()。

    open class Bird {
        open var color = "Black"
        open fun fly() {
          println("Bird is flying...")
        }
    }
    interface Duck {
         fun fly() {
          println("Duck is flying...")
        }
    }
    class Parrot: Bird(),Duck {
        override var color = "Green"
        override fun fly() {
            super<Bird>.fly()
            super<Duck>.fly()
            println("Parrot is flying...")
    
        }
    }
    fun main(args: Array<String>) {
        val p = Parrot()
        p.fly()
        println(p.color)
    
    }

    输出:

    Bird is flying...
    Duck is flying...
    Parrot is flying...
    

    祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

    技术教程推荐

    AI技术内参 -〔洪亮劼〕

    iOS开发高手课 -〔戴铭〕

    从0开发一款iOS App -〔朱德权〕

    编辑训练营 -〔总编室〕

    性能测试实战30讲 -〔高楼〕

    说透敏捷 -〔宋宁〕

    深度学习推荐系统实战 -〔王喆〕

    大厂广告产品心法 -〔郭谊〕

    自动化测试高手课 -〔柳胜〕

    好记忆不如烂笔头。留下您的足迹吧 :)