对比Java学Kotlin接口
Posted 陈蒙_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对比Java学Kotlin接口相关的知识,希望对你有一定的参考价值。
在 Java 中,接口可以看成是抽象类的更进一步抽象,在 Kotlin 中也是这样的。
在 Kotlin 中,接口与抽象类的不同表现在:
- 用 interface 声明,抽象方法可以省略 abstract 关键字;
- 成员变量必须是 abstract 的,否则需要提供 get() 方法的实现;
根据上面的描述,我们得知 Kotlin 接口是可以含有普通方法的,这一点是跟 Java 不同的:
interface IFly
fun fly() // 省略了 abstract 关键字
fun accelerate() // 已经实现的普通方法
在 Kotlin 中,我们不用在像 Java 那样,继承基类使用 extends 关键字、实现接口使用 implements 关键字,徒增记忆负担。在 Kotlin 中我们实现接口的方式也与抽象类是一致的,只需要一个冒号就行了:
class Bird : IFly
override fun fly()
属性
说到属性,这是跟 Java 差别较大的部分。Kotlin 的属性必须是 abstract 的,否则必须提供获取该属性的 get() 方法。这是因为接口中的属性没有影子字段(backing field),无法使用默认的 get() 方法来引用他们。
interface IFly
val speed: Int
val wings: String
get() = "wings"
fun fly()
class Bird : IFly
override val speed: Int = 30
override fun fly()
TODO("Not yet implemented")
继承其他接口
与 Java 一样,Kotlin 中的接口也可以继承其他的接口:
interface Named
val name: String
interface Person : Named
val firstName: String
val lastName: String
override val name: String
get() = "$firstName $lastName" // name 已经实现了
data class Employee(
override val firstName: String,
override val lastName: String,
val position: Int
) : Person
方法冲突
如果一个类实现了多个接口,多个接口里面有完全相同的方法签名,这时会发生什么?
interface A
fun foo()
println("A")
fun bar()
interface B
fun foo()
println("B")
fun bar()
println("bar")
class C : A
override fun bar()
println("bar")
class D : A, B
// 如果不实现该方法,编译器会报错:
// Class 'D' must override public open fun foo():
// Unit defined in com.dianping.base.ugc.service.A because it inherits multiple interface methods of it
override fun foo()
super<A>.foo()
super<B>.foo()
override fun bar()
super.bar()
接口 A 和 B 里面都有 foo() 和 bar(),二者都实现了 foo(),只有 B 实现了 bar()。
对于 C,很简单,按照规则实现接口的抽象方法 bar() 即可。
比较特殊的是 D,D 同时实现了 A 和 B 两个接口,而且二者中含有相同的方法签名 foo() 和 bar()。这时我们需要把 foo() 和 bar() 都实现才行。
在 Java 中是怎么样的?
首先,Java 中的接口是不能含有已经实现的的方法的。所以 Java 中不存在 Kotlin 中必须要实现接口中已经实现了 foo() 方法的现象。
如果多个接口中含有相同的方法签名,是都要实现的:
public interface A
void foo();
void bar();
public interface B
void foo();
void bar();
public class D implements A, B
@Override
public void foo()
@Override
public void bar()
方法型接口
从 1.4 版本开始,如果一个接口只含有一个抽象方法,我们称这样的接口为方法型接口,或者孤独抽象方法(SAM,single abstract method)。方法型接口里面还可以有多个非抽象方法。
在 Kotlin 中我们使用 fun 修饰符来声明方法型接口:
fun interface KRunnable
fun invoke()
SAM 转换
SAM 的好处是,我们可以使用 lambda 表达式来让代码更加简洁和具有更好的可读性。
通常当我们使用接口时,我们需要为接口创建一个对象再使用。而当我们使用 SAM 时,我们可以直接使用 lamdbda 表达式,然后编译器会自动帮我们做转换,把 lambda 表达式转换成对应的对象。
我们有一个 SAM:
fun interface IntPredicate
fun accept(i: Int): Boolean
支持情况下我们的使用方法是:
// 创建接口的对象
val isEven = object : IntPredicate
override fun accept(i: Int): Boolean
return i % 2 == 0
借助 SAM 转换,我们可以使用 lambda 表达式来完成:
val isEven = IntPredicate i -> i % 2 == 0
对于我们在安卓开发中经常使用的接口,比如 Runnable、OnClickListener 等只含有一个抽象方法的接口,都是可以使用 SAM 转换的:
mButton.setOnClickListener
// do something
以上是关于对比Java学Kotlin接口的主要内容,如果未能解决你的问题,请参考以下文章