Kotlin教程:继承示例、方法覆盖、超类实现

2020-04-2311:31:25编程语言入门到精通Comments1,936 views字数 5938阅读模式

继承是面向对象编程语言的一个重要特征。 继承允许将类(或基类或父类)的特性继承到新类(或派生类或子类)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

主类称为超类(或父类),继承超类的类称为子类(或子类)。 子类包含超类的特性以及它自己的特性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

当两个或多个类具有相同的属性时,这就引入继承的概念。 继承用于提高代码可重用性。 派生类只有一个基类,但可以有多个接口,而基类可能有一个或多个派生类。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

在Kotlin中,派生类在类头中使用冒号(:)操作符来继承基类(在派生类名或构造函数之后)。如下代码所示 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

// 声明一个基类
open class Base(p: Int){  

}

// 声明一个继承自 Base 类(也称为基类)的子类:Derived
class Derived(p: Int) : Base(p){  

}
Kotlin

假设有两个不同的类:ProgrammerSalesman,它们具有公共属性nameagesalary以及它们各自的方法:functionalitiesdoProgram()fieldWork()。 继承的特性允许继承包含公共特性的(Employee基类)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

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

所有Kotlin类都有一个共同的超类Any,它是没有明确指定超类时使用的默认超类。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

例如,类Example是隐式继承Any类的,即使没有明确写上。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

class Example
Kotlin

Kotlin open关键字

由于Kotlin类默认为final,因此不能简单地继承它们。在类之前使用open关键字来为其它类继承这个类。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

open class Example{  
// I can now be extended!  
}
Kotlin

Kotlin继承类中的字段

当继承一个类来派生类时,所有的字段和函数都是继承的。 可以在派生类中使用这些字段和函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

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()
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

x is equal to 10
Shell

Kotlin从类继承方法

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()
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

flying...
swimming...
Shell

Kotlin继承示例

在这里,声明一个类Employee是超类,ProgrammerSalesman是它的子类。 子类继承属性:name, agesalary 以及包含子类自身的函数,如:doProgram()fieldWork()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

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 hobby.")
    }
}
fun main(args: Array<String>){
    val obj1 = Programmer("Maxsu", 25, 40000f)
    obj1.doProgram()
    val obj2 = Salesman("Ajax", 24, 30000f)
    obj2.fieldWork()
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Name is Maxsu.
Age is 25
Salary is 40000.0
programming is my passion.
Name is Ajax.
Age is 24
Salary is 30000.0
travelling is my hobby.
Shell

Kotlin继承和主要构造函数

如果基类和派生类都具有主构造函数,则参数在基类的主构造函数中初始化。 在上面的继承示例中,所有类都包含三个参数:nameagesalary,所有这些参数都在基类的主构造函数中初始化。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

当基类和派生类在主构造函数中包含不同数量的参数时,基类参数将从派生类对象初始化。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

示例代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

open class Employee(name: String,salary: Float) {
    init {
        println("姓名:$name.")
        println("薪水:$salary")
    }
}
class Programmer(name: String, dept: String, salary: Float):Employee(name,salary){
    init {
        println("$name 所在部门:$dept ,薪水为:$salary.")
    }
    fun doProgram() {
        println("编程我有激情.")

    }
}
class Salesman(name: String, dept: String, salary: Float):Employee(name,salary){
    init {
        println("$name 所在部门:$dept ,薪水为:$salary.")
    }
    fun fieldWork() {
        println("我的爱好是:旅游.")

    }
}
fun main(args: Array<String>){
    val obj1 = Programmer("Susen", "技术部", 40000f)
    obj1.doProgram()
    println()
    val obj2 = Salesman("Ajax", "市场部", 30000f)
    obj2.fieldWork()
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

姓名:Susen.
薪水:40000.0
Susen 所在部门:技术部 ,薪水为:40000.0.
编程我有激情.

姓名:Ajax.
薪水:30000.0
Ajax 所在部门:市场部 ,薪水为:30000.0.
我的爱好是:旅游.
Shell

当创建派生类的对象时,它首先调用超类并执行基类的init块,然后执行它自己的init块。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Kotlin继承和辅助构造函数

如果派生类不包含任何主构造函数,则需要使用super关键字从派生类调用基类辅助构造函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

open class Patent {

    constructor(name: String, id: Int) {
        println("执行超类构造函数: $id$name ")
    }
}

class Child: Patent {

    constructor(name: String, id: Int, dept: String): super(name, id) {
        print("使用属性执行子类构造函数:$name, $id, $dept")
    }
}
fun main(args: Array<String>) {
    val child = Child("Maxsu",10010, "技术部")
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

执行超类构造函数: 10010 , Maxsu 
使用属性执行子类构造函数:Maxsu, 10010, 技术部
Shell

在上面的示例中,当创建Child类的对象时,它调用其构造函数并使用值:“Maxsu”,“10010”和“技术部”初始化其参数。 同时,Child类构造函数使用具有nameid值的super关键字调用超类的构造函数。 由于super关键字的存在,超类构造函数的主体首先执行并返回到Child类构造函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Kotlin方法覆盖

方法覆盖意味着将super(parent)类的方法的特定实现提供到子类(子)类中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

换句话说,当子类重新定义或修改其超类的方法为子类时,它被称为方法覆盖。 方法覆盖只能在继承中实现。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Kotlin方法覆盖的规则文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

  • 父类及要覆盖的方法或属性必须是open的(非final)。
  • 基类和派生类的方法名必须相同。
  • 方法必须具有与基类相同的参数。

没有覆盖的继承示例

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()
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

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

在上面的例子中,一个没有覆盖基类方法的程序出现派生类ParrotDuck类执行相同的操作。 为了克服这个问题,使用方法覆盖这个概念。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Kotlin方法覆盖的示例

在此示例中,子类ParrotDuck中覆盖父类Bird的方法fly()。 要覆盖父类的方法,必须将要覆盖的父类及方法声明为open。 同时,在子类中重写的方法必须以override关键字开头。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

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()
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

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

Kotlin属性覆盖的示例

超类的属性也可以在子类中覆盖,这个实现类似于方法。 在子类ParrotDuck中重写并修改Bird类的color属性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

open class Bird {
    open var color = "黑色"
    open fun fly() {
        println("Bird is flying...")
    }
}
class Parrot: Bird() {
    override var color = "绿色"
    override fun fly() {
        println("Parrot is flying...")
    }
}
class Duck: Bird() {
    override var color = "花色"
    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)
}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Parrot is flying...
绿色
Duck is flying...
花色
Shell

可以在继承中使用var属性覆盖val属性,但反之亦然。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Kotlin超类实现

派生类也可以使用super关键字调用超类方法和属性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

例如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

open class Bird {
    open var color = "黑色"
    open fun fly() {
        println("Bird is flying...")
    }
}
class Parrot: Bird() {
    override var color = "绿色"
    override fun fly() {
        super.fly()
        println("Parrot is flying...")
    }
}

fun main(args: Array<String>) {
    val p = Parrot()
    p.fly()
    println(p.color)

}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Bird is flying...
Parrot is flying...
绿色
Shell

Kotlin多类实现

在Kotlin中,派生类在尖括号中使用超类型名称,即,super <Base>,当它实现多个类中提供的相同函数名时。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

例如,派生类Parrot扩展超类Bird并实现相同的Duck接口函数fly()。 要调用每个类和接口的特定方法,必须在尖括号中提到超类型名称为super <Bird>.fly()super <Duck>.fly()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

open class Bird {
    open var color = "黑色"
    open fun fly() {
        println("Bird is flying...")
    }
}
interface Duck {
    fun fly() {
        println("Duck is flying...")
    }
}
class Parrot: Bird(),Duck {
    override var color = "绿色"
    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)

}
Kotlin

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

Bird is flying...
Duck is flying...
Parrot is flying...
绿色

//原文出自【易百教程】,商业转载请联系作者获得授权,非商业转载请保留原文链接:https://www.yiibai.com/kotlin/kotlin-inheritance.html#article-start文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/18299.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/18299.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定