《Kotlin核心编程》 ——3.3.2 接口实现多继承

举报
华章计算机 发表于 2020/02/21 22:46:22 2020/02/21
【摘要】 本节书摘来自华章计算机《Kotlin核心编程》 —— 书中第3章,第3.3.2节,作者是水滴技术团队 。

3.3.2 接口实现多继承

一个类实现多个接口相信你肯定不会陌生,这是Java经常干的事情。Kotlin中的接口与Java很相似,但它除了可以定义带默认实现的方法之外,还可以声明抽象的属性。我们的第1个方案,就来看看如何用Kotlin中的接口来实现多继承。

interface Flyer {

    fun fly()

    fun kind() = "flying animals"

}

 

interface Animal {

    val name: String

    fun eat()

    fun kind() = "flying animals"

}

 

class Bird(override val name: String) : Flyer, Animal {

    override fun eat() {

        println("I can eat")

    }

 

    override fun fly() {

        println("I can fly")

    }

 

    override fun kind() = super<Flyer>.kind()

}

 

fun main(args: Array<String>) {

    val bird = Bird("sparrow")

    println(bird.kind())

}

// 运行结果

flying animals

如你所见,Bird类同时实现了Flyer和Animal两个接口,但由于它们都拥有默认的kind方法,同样会引起上面所说的钻石问题。而Kotlin提供了对应的方式来解决这个问题,那就是super关键字,我们可以利用它来指定继承哪个父接口的方法,比如上面代码中的super<Flyer>.kind()。当然我们也可以主动实现方法,覆盖父接口的方法。如:

override fun kind() = "a flying ${this.name}"

那么最终的执行结果就是:

a flying sparrow

通过这个例子,我们再来分析下实现接口的相关语法:

1)在Kotlin中实现一个接口时,需要实现接口中没有默认实现的方法及未初始化的属性,若同时实现多个接口,而接口间又有相同方法名的默认实现时,则需要主动指定使用哪个接口的方法或者重写方法;

2)如果是默认的接口方法,你可以在实现类中通过“super<T>”这种方式调用它,其中T为拥有该方法的接口名;

3)在实现接口的属性和方法时,都必须带上override关键字,不能省略。

除此之外,你应该还注意到了,我们通过主构造方法参数的方式来实现Animal接口中的name属性。我们之前说过,通过val声明的构造方法参数,其实是在类内部定义了一个同名的属性,所以我们当然还可以把name的定义放在Bird类内部。

class Bird(name: String) : Flyer, Animal {

    override val name: String // override不要忘记

 

    init {

        this.name = name

    }

}

name的赋值方式其实无关紧要。比如我们还可以用一个getter对它进行赋值。

class Bird(chineseName: String) : Flyer, Animal {

    override val name: String

        get() = translate2EnglishName(chineseName)

}

getter和setter

对于getter和setter相信很多Java程序员再熟悉不过了,在Java中通过这种方式来对一个类的私有字段进行取值和赋值的操作,通常用IDE来帮我们自动生成这些方法。但是在很多时候你会发现这种语法真是不堪入目。而Kotlin类不存在字段,只有属性,它同样需要为每个属性生成getter和setter方法。但Kotlin的原则是简洁明了的,既然都要做,那么为何我不幕后就帮你做好了呢?所以你在声明一个类的属性时,要知道背后Kotlin编译器也帮你生成了getter和setter方法。当然你也可以主动声明这两个方法来实现一些特殊的逻辑。还有以下两点需要注意:

1)用val声明的属性将只有getter方法,因为它不可修改;而用var修饰的属性将同时拥有getter和setter方法。

2)用private修饰的属性编译器将会省略getter和setter方法,因为在类外部已经无法访问它了,这两个方法的存在也就没有意义了。

总的来说,用接口模拟实现多继承是我们最常用的方式。但它有时在语义上依旧并不是很明确。下面我们就来看一种更灵活的方式,它能更完整地解决多继承问题。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。