Kotlin 继承和接口

一、Kotlin中类的继承

在Java中,类基于Object,而在Kotlin中类基于Any,所有类都默认继承Any。kotlin中的类默认是final类型的,不可被继承,想要作为基类被继承必须使用open关键字修饰。

对于没有超类型声明的类默认超类是Any,Any类只有三个函数~


package kotlin

public open class Any {
   
    public open operator fun equals(other: Any?): Boolean

    public open fun hashCode(): Int

    public open fun toString(): String
}

二、子类对构造函数的实现

1.当子类中有构造函数,则基类必须在主构造函数中立即初始化

open class S(name: String, age: Int) { //基类

}

//子类中有构造函数,则基类必须在主构造函数中立即初始化
class SS(var name: String, val age: Int, val score: Int) : S(name, age) {

}
fun main(args: Array<String>) {
    val s = SS("Tina", 20, 60)
    println("学生名:${s.name}")
    println("年龄:${s.age}")
    println("成绩:${s.score}")

}
学生名:Tina
年龄:20
成绩:60

2.当子类中没有主构造函数时,则必须每一个次要构造函数或代理另一个构造函数中用 super 关键字初始化基类。初始化基类时,可以使用super来调用基类的不同构造函数。

open class Personal(name: String) {
    constructor(name: String, age: Int) : this(name) {
        //初始化
        println("---基类次级构造函数-----")
    }
}

class SrudentImpl : Personal {
    constructor(name: String, age: Int, no: String, score: Int, likely: String) : super(name, age) {
        println("----- 继承类的次级构造函数 ------")
        println("学生名:${name}")
        println("年龄:${age}")
        println("学生号:${no}")
        println("成绩:${score}")
    }
}
fun main(args: Array<String>) {
    var student = SrudentImpl("Mikle", 18, "12485684", 98, "唱歌")
}
学生名:Mikle
年龄:18
学生号:12485684
成绩:98

3.方法的重写

基类中,使用fun声明函数时,该函数默认是final修饰的,不能被子类重写。如果允许该函数能被重写,则需手动添加open修饰它,子类复写使用override关键词。

open class D {
    open fun study() {  //允许子类重写的方法
        println("基类DD中定义需被子类重写的方法")
    }
}

class DD : D(), F {
    override fun study() {
        println("子类重写了父类的方法~~~")
        super<D>.study()
        super<F>.study()
    }
}

interface F {
    fun study() {  //允许子类重写的方法
        println("接口F中定义的方法~~")
    }
}

4.属性重写:使用override关键字

interface Foo {
    val count: Int
}

//属性的复写使用override关键字
class Bar1(override val count: Int) : Foo {}

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

三、Kotlin中接口的实现

使用关键字interface定义接口,一个类可实现一个或多个接口

interface MyInterface {
    val name:String  //接口中的属性只能是抽象的,不允许初始化值,实现接口,必须重写属性
    fun bar()
    fun foo()
}

class Child: MyInterface {
    override var name:String="我是复写的name属性"  //重写属性
    override fun foo() {
        println("调用了foo方法")
    }

    override fun bar() {
       println("调用了bar方法")
    }
}

fun main(args: Array<String>) {
    val c = Child()
    c.foo()
    c.bar()
    println(c.name)
}
调用了foo方法
调用了bar方法
我是复写的name属性

***当实现多个接口时,可能会遇到同一方法继承多个实现的问题。

interface A {
    fun foo() {
        println("A")
    }  //有方法体,代表已经实现

    fun bar() //无方法体,是抽象的,未实现,需要被子类重写
}

interface B {
    fun foo() {
        println("B") //已实现
    }

    fun bar() {
        println("bar") //已实现
    }
}

class C : A {
    override fun bar() {
    }
}

class H : A, B {
    override fun bar() {
        super<B>.bar()
    }

    override fun foo() {
        super<A>.foo()
        super<B>.foo()
    }
}

fun main(args: Array<String>) {
   val h=H()
    h.foo()
    h.bar()
}
调用了foo方法
调用了bar方法
我是复写的name属性

 

 

### Kotlin继承的使用方法 在 Kotlin 中,类默认是不可被继承的(即 `final` 的),如果希望某个类可以被其他类继承,则需要显式地将其标记为 `open` 关键字[^1]。 #### 基本继承示例 下面是一个简单的继承示例: ```kotlin // 定义一个开放的基类 open class Person { open fun displayInfo() { println("This is a person.") } } // 子类继承自 Person 类 class Student : Person() { override fun displayInfo() { println("This is a student who inherits from Person.") } var sno = "" var grade = 0 } ``` 在这个例子中,`Person` 是父类,而 `Student` 是子类。通过 `:` 符号指定 `Student` 继承自 `Person`。注意,在 Kotlin 中,只有当父类被标记为 `open` 时才能被继承[^4]。 --- #### 构造函数中的继承 Kotlin 支持主构造函数次构造函数的概念。在继承过程中,子类可以通过其主构造函数调用父类的主构造函数来完成初始化[^3]。 以下是带有参数化构造函数的继承示例: ```kotlin // 父类带有一个主构造函数 open class Animal(val name: String) { init { println("Animal initialized with name $name") } } // 子类通过主构造函数调用父类的主构造函数 class Dog(name: String, val breed: String) : Animal(name) { init { println("Dog initialized with breed $breed") } } fun main() { val myDog = Dog("Buddy", "Golden Retriever") // 输出两条日志消息 } ``` 在此代码片段中,`Dog` 类通过 `(name)` 调用了 `Animal` 类的主构造函数,并额外添加了自己的属性 `breed` 相应的逻辑。 --- #### 方法重写的规则 在 Kotlin 中,任何可被子类覆盖的方法都需要显式地标记为 `open`。同样地,子类在实现这些方法时也需要使用 `override` 关键字表明这是对父类方法的覆写行为[^2]。 以下是对方法重写的演示: ```kotlin open class Vehicle { open fun startEngine() { println("Vehicle engine started.") } } class Car : Vehicle() { override fun startEngine() { println("Car engine started.") // 自定义实现 } } fun main() { val car = Car() car.startEngine() // 执行的是 Car 的版本 } ``` 上述代码展示了如何利用 `override` 来修改父类的行为。 --- #### 默认继承 Any 类 即使未明确声明父类,Kotlin 中的所有类都会隐式地继承自 `Any` 类。这类似于 Java 中的对象层次结构[^5]。 ```kotlin class Person // 隐式继承自 Any fun main() { val person = Person() println(person.toString()) // 调用来自 Any 的 toString 方法 } ``` 在这里可以看到,默认情况下可以直接访问 `toString()`、`equals()` `hashCode()` 这些由 `Any` 提供的基础功能。 --- #### 多接口继承的设计哲学 需要注意的是,为了避免多继承带来的复杂性潜在问题(如经典的“菱形继承”难题),Kotlin 不支持直接从多个具体类派生。然而,它提供了对接口的支持以及组合模式作为替代方案。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值