在Kotlin中,interface 是一种抽象类型,你可以从中列出特定的属性和方法,这些属性和方法必须由实现上述interface 的其他类或接口来实现。
使用interface 的目的是为了确保任何实现了interface 的类都会有现成的属性和方法供你在程序中调用和使用。
在Kotlin中,一个interface 可能有以下定义:
- 要由他人实现的抽象方法
- 某些方法的实现
- 抽象属性(变量)
- 带有访问器的抽象属性
接下来让我们看看如何将这些定义添加到一个interface ,首先是添加抽象方法。
Kotlin接口的抽象方法
首先,让我们在Kotlin中创建一个名为Animal 的interface ,如下:
interface Animal {
fun sleep()
}
在上面的代码中,函数sleep() 是一个抽象函数,需要由任何实现了Animal 接口的class 来实现。
接下来,让我们创建一个实现了Animal 接口的Dog 类:
class Dog: Animal
上面的Dog 类会引起一个静态错误,说这个类不是抽象的,它没有实现抽象成员sleep() 。
换句话说,你需要在Dog 类中定义sleep() 方法的作用。
下面的例子应该可以解决这个错误:
class Dog: Animal {
override fun sleep() {
println("The dog is sleeping")
}
}
override 关键字意味着你正在覆盖从其他类或接口继承的函数。
带有实现的Kotlin接口方法
另外,一个interface ,也可以定义特定方法的实现,这些方法可以被实现的class 成员访问。
在下面的例子中,Animal 接口有对sleep() 方法的实现:
interface Animal {
fun sleep() {
println("The animal is sleeping")
}
}
当一个interface 函数有自己的实现时,你不需要在实现的class 里面覆盖这个函数。
class 实例可以直接调用该方法,如下图所示:
class Dog : Animal
val myDog = Dog()
myDog.sleep() // The animal is sleeping
现在你已经学会了如何在一个interface 中创建抽象和非抽象方法。
接下来让我们看看如何创建抽象属性。
Kotlin接口抽象属性
一个Kotlininterface 允许你创建需要由class 实现的抽象属性。
例如,Animal 接口可能有一个scientificName 变量,它的抽象性如下:
interface Animal {
val scientificName: String
}
当你对Dog 类实现Animal 接口时,你需要提供该变量的值,如下图所示:
class Dog : Animal {
override val scientificName = "Canidae"
}
这确保你以后创建的任何类实例都能访问scientificName 变量:
val myDog = Dog()
println(myDog.scientificName) // Canidae
你可以在一个interface 类型中添加你需要的任意数量的抽象属性,如下图所示:
interface Animal {
val scientificName: String
val feet: Int
val canFly: Boolean
}
带有访问器的Kotlin接口
另外,你可以创建一个带有访问器的属性(set 和get 方法)来修改你的变量被访问时的行为。
在一个interface ,你不能像下面这样初始化一个属性:
interface Animal {
val scientificName: String = "unidentified"
}
要在interface 中初始化一个属性,你需要使用get() 方法,如下所示:
interface Animal {
val scientificName: String
get() = "unidentified"
}
通过在scientificName 属性中定义的访问器get() ,你可以在你的class 定义中跳过重写该属性。
看一下下面的例子:
interface Animal {
val scientificName: String
get() = "undefined"
}
class Dog : Animal
val myDog = Dog()
println(myDog.scientificName) // undefined
一个interface 中的抽象属性通常被定义为最终变量(使用val 关键字)
正因为如此,你不需要在该属性中实现一个set() 方法。一旦初始化,其值就不能被改变。
用相同的属性或方法实现多个接口
因为你可以对一个class 多个接口,所以你的类有可能实现了接口中相同的属性或方法。
当你的接口有相同类型的属性名称时,那么你就可以按照下面的方法覆盖该属性:
interface Animal {
val scientificName: String
}
interface Species {
val scientificName: String
}
class Dog : Animal, Species {
override val scientificName: String = "Canidae"
}
但是当你的接口有不同类型的属性名时,就会发生冲突:
interface Animal {
val scientificName: String
}
interface Species {
val scientificName: Int
// ^ The same property name with a different type
}
class Dog : Animal, Species {
override val scientificName: String = "Canidae"
}
当你开发一个Kotlin应用程序时,上面的假想情况不应该发生。
但是当它真的发生时,那么你需要确保你为scientificName 属性使用相同的变量类型。
最后,当你有多个方法名称相同的接口时,那么class 必须有自己的相同方法的实现。
考虑一下下面的例子:
interface Animal {
fun sleep() {
println("ZzZ")
}
}
interface Species {
fun sleep() {
println("Sleeping")
}
}
class Dog : Animal, Species {
override fun sleep() {
println("Good night!")
}
}
val myDog = Dog()
myDog.sleep() // Good night!
class 方法的实现告诉Kotlin,当class 实例调用该方法时要执行哪种实现。
而这就是interface 类型在Kotlin中的工作方式。它允许你定义实现interface 的class 应该有的属性和方法。
虽然你可能有多个接口有相同的属性或方法名称,但你需要仔细思考你的源代码,并尽量避免有相同名称的属性或方法。
在学习Kotlin接口方面做得很好!😉