继承是面向对象编程语言的一个重要特征。 继承允许将类(或基类或父类)的特性继承到新类(或派生类或子类)。
主类称为超类(或父类),继承超类的类称为子类(或子类)。 子类包含超类的特性以及它自己的特性。
当两个或多个类具有相同的属性时,这就引入继承的概念。 继承用于提高代码可重用性。 派生类只有一个基类,但可以有多个接口,而基类可能有一个或多个派生类。
在Kotlin中,派生类在类头中使用冒号(:
)操作符来继承基类(在派生类名或构造函数之后)。如下代码所示 -
// 声明一个基类
open class Base(p: Int){
}
// 声明一个继承自 Base 类(也称为基类)的子类:Derived
class Derived(p: Int) : Base(p){
}
Kotlin
假设有两个不同的类:Programmer
和Salesman
,它们具有公共属性name
,age
和salary
以及它们各自的方法:functionalitiesdoProgram()
和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
所有Kotlin类都有一个共同的超类Any
,它是没有明确指定超类时使用的默认超类。
例如,类Example
是隐式继承Any
类的,即使没有明确写上。
class Example
Kotlin
Kotlin open关键字
由于Kotlin类默认为final
,因此不能简单地继承它们。在类之前使用open
关键字来为其它类继承这个类。
示例:
open class Example{
// I can now be extended!
}
Kotlin
Kotlin继承类中的字段
当继承一个类来派生类时,所有的字段和函数都是继承的。 可以在派生类中使用这些字段和函数。
示例:
open class Base{
val x = 10
}
class Derived: Base() {
fun foo() {
println("x is equal to " + x)
}
}
fun main(args: Array) {
val derived = Derived()
derived.foo()
}
Kotlin
执行上面示例代码,得到以下结果 -
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) {
val duck = Duck()
duck.fly()
duck.swim()
}
Kotlin
执行上面示例代码,得到以下结果 -
flying...
swimming...
Shell
Kotlin继承示例
在这里,声明一个类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 hobby.")
}
}
fun main(args: Array){
val obj1 = Programmer("Maxsu", 25, 40000f)
obj1.doProgram()
val obj2 = Salesman("Ajax", 24, 30000f)
obj2.fieldWork()
}
Kotlin
执行上面示例代码,得到以下结果 -
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继承和主要构造函数
如果基类和派生类都具有主构造函数,则参数在基类的主构造函数中初始化。 在上面的继承示例中,所有类都包含三个参数:name
,age
和salary
,所有这些参数都在基类的主构造函数中初始化。
当基类和派生类在主构造函数中包含不同数量的参数时,基类参数将从派生类对象初始化。
示例代码
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){
val obj1 = Programmer("Susen", "技术部", 40000f)
obj1.doProgram()
println()
val obj2 = Salesman("Ajax", "市场部", 30000f)
obj2.fieldWork()
}
Kotlin
执行上面示例代码,得到以下结果 -
姓名:Susen.
薪水:40000.0
Susen 所在部门:技术部 ,薪水为:40000.0.
编程我有激情.
姓名:Ajax.
薪水:30000.0
Ajax 所在部门:市场部 ,薪水为:30000.0.
我的爱好是:旅游.
Shell
当创建派生类的对象时,它首先调用超类并执行基类的init
块,然后执行它自己的init
块。
Kotlin继承和辅助构造函数
如果派生类不包含任何主构造函数,则需要使用super
关键字从派生类调用基类辅助构造函数。
示例:
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) {
val child = Child("Maxsu",10010, "技术部")
}
Kotlin
执行上面示例代码,得到以下结果 -
执行超类构造函数: 10010 , Maxsu
使用属性执行子类构造函数:Maxsu, 10010, 技术部
Shell
在上面的示例中,当创建Child
类的对象时,它调用其构造函数并使用值:“Maxsu”,“10010”和“技术部”初始化其参数。 同时,Child
类构造函数使用具有name
和id
值的super
关键字调用超类的构造函数。 由于super
关键字的存在,超类构造函数的主体首先执行并返回到Child
类构造函数。
Kotlin方法覆盖
方法覆盖意味着将super(parent)
类的方法的特定实现提供到子类(子)类中。
换句话说,当子类重新定义或修改其超类的方法为子类时,它被称为方法覆盖。 方法覆盖只能在继承中实现。
Kotlin方法覆盖的规则
- 父类及要覆盖的方法或属性必须是
open
的(非final
)。 - 基类和派生类的方法名必须相同。
- 方法必须具有与基类相同的参数。
没有覆盖的继承示例
open class Bird {
open fun fly() {
println("Bird is flying...")
}
}
class Parrot: Bird() {
}
class Duck: Bird() {
}
fun main(args: Array) {
val p = Parrot()
p.fly()
val d = Duck()
d.fly()
}
Kotlin
执行上面示例代码,得到以下结果 -
Bird is flying...
Bird is flying...
Shell
在上面的例子中,一个没有覆盖基类方法的程序出现派生类Parrot
和Duck
类执行相同的操作。 为了克服这个问题,使用方法覆盖这个概念。
Kotlin方法覆盖的示例
在此示例中,子类Parrot
和Duck
中覆盖父类Bird
的方法fly()
。 要覆盖父类的方法,必须将要覆盖的父类及方法声明为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) {
val p = Parrot()
p.fly()
val d = Duck()
d.fly()
}
Kotlin
执行上面示例代码,得到以下结果 -
Parrot is flying...
Duck is flying...
Shell
Kotlin属性覆盖的示例
超类的属性也可以在子类中覆盖,这个实现类似于方法。 在子类Parrot
和Duck
中重写并修改Bird
类的color
属性。
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) {
val p = Parrot()
p.fly()
println(p.color)
val d = Duck()
d.fly()
println(d.color)
}
Kotlin
执行上面示例代码,得到以下结果 -
Parrot is flying...
绿色
Duck is flying...
花色
Shell
可以在继承中使用var
属性覆盖val
属性,但反之亦然。
Kotlin超类实现
派生类也可以使用super
关键字调用超类方法和属性。
例如:
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) {
val p = Parrot()
p.fly()
println(p.color)
}
Kotlin
执行上面示例代码,得到以下结果 -
Bird is flying...
Parrot is flying...
绿色
Shell
Kotlin多类实现
在Kotlin中,派生类在尖括号中使用超类型名称,即,super
,当它实现多个类中提供的相同函数名时。
例如,派生类Parrot
扩展超类Bird
并实现相同的Duck接口函数fly()
。 要调用每个类和接口的特定方法,必须在尖括号中提到超类型名称为super .fly()
和super .fly()
。
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.fly()
super.fly()
println("Parrot is flying...")
}
}
fun main(args: Array) {
val p = Parrot()
p.fly()
println(p.color)
}
Kotlin
执行上面示例代码,得到以下结果 -
Bird is flying...
Duck is flying...
Parrot is flying...
绿色
//原文出自【易百教程】,商业转载请联系作者获得授权,非商业转载请保留原文链接:https://www.yiibai.com/kotlin/kotlin-inheritance.html#article-start