之前在类的继承中,我们已经提到了接口,本片博客我们来详细讲讲接口
首先要重点说一下:Kotlin中的Lambda表达式和Java中的Lambda表达式有点不一样
Kotlin中lambda表达式是,实现一个函数,而Java中是实现函数式接口
Kotlin中函数可以当做函数的参数:
fun getArraySum(array: Array<Int>,add:(a:Int,b:Int) -> Int):Int{ //add 就是一个参数为(a:Int,b:Int)返回值为Int型的函数
var sum = 0
for (item in array){
sum = add(sum,item)
}
return sum
}
fun main(args: Array<String>) {
var array = arrayOf(1,2,3,4,5,6)
var sum = getArraySum(array){ a,b -> a+b } //用lambda表达式实现函数
}
而在Java里:
首先我们要有函数式接口:
//这就是一个函数是的接口
public interface Add {
int add(int a,int b);
}
然后我们才能使用lambda表达式实现函数式接口:
public class LambdaTest {
public static void main(String[] args) {
//实现Add函数式接口
Add a = (x,y) -> x + y; //返回的是接口类型
int add = a.add(1,3);
System.out.println(add);
}
}
根据以上的分别,我们要注意以下几点
1. Kotlin中并没有函数式接口,lambda表达式只能实现函数声明
2. Kotlin要实现函数式接口,也只能实现Java的函数式接口
3. Kotlin和Java相比较,还是Kotlin简单,因为Kotlin实现函数声明返回的是声明的类型,直接用这个类型的引用调用方法就好。而Java还要通过接口类型的实现类的对象的引用来调用实现的方法(表达起来都拗口)
4. 但是两者相同点是:两个实现的最终目标是函数或者接口
题外话说了很久,我们来说这篇博客的主题:接口
接口的声明和实现
Kotlin 的接⼝与 Java 8 类似,既包含抽象⽅法的声明,也包含实现。与抽象类不同的是,接⼝⽆法保存状态。它可以有属性但必须声明为抽象或提供访问器实现
get一下上面的信息点:
1. Kotlin接口中属性要么是抽象的,要么提供访问器实现
2. Kotlin接口中方法要么是抽象的,要么实现它(有方法体)
3. 抽象类能保存状态,接口不能保存状态
接口的声明
使⽤关键字 interface 来定义接⼝:
interface MyInterface {
fun bar()
fun foo() {
// 可选的⽅法体,这里能有方法体里面的代码
}
}
实现接⼝:
⼀个类或者对象可以实现⼀个或多个接⼝。
class Child : MyInterface {
override fun bar() {
// ⽅法体
}
}
接口里的属性
你可以在接⼝中定义属性。在接⼝中声明的属性要么是抽象的,要么提供访问器的实现。在接⼝中声明的属性不能有幕后字段(backing field),因此接⼝中声明的访问器不能引⽤它们
再次get一下上面的意思:
1,接口中的属性要么是抽象的,一定会被覆盖,要么就是提供访问器的
2. 接口中属性没有幕后字段,所以不可能只实现一个访问器,默认一个。要么两个都实现,要么属性是val类型的,实现其getter
interface A{
val bb :String //因为幕后字段不能用,所以一般情况下要实现访问器的只有val类型的属性
get() = "lal"
var aa : Int
}
class AA :A {
override var aa: Int = 9
}
解决覆盖冲突
实现多个接⼝时,可能会遇到同⼀⽅法继承多个实现的问题。例如
//声明两个接口
interface A {
fun foo() { print("A") } //和接口B中的foo函数同名
fun bar()
}
interface B {
fun foo() { print("B") } //和接口A中的foo函数同名
fun bar() { print("bar") }
}
class C : A { //类C只实现了一个接口,不要解决冲突
override fun bar() { print("bar") }
}
class D : A, B { //类D实现了两个接口,要符合覆盖规则,所以要解决冲突
override fun foo() { //为了不冲突,提供自己的实现
super<A>.foo()
super<B>.foo()
}
override fun bar() {//为了不冲突,提供自己的实现
super<B>.bar()
}
}
下面再帖一下官方的说明:
上例中,接⼝ A 和 B 都定义了⽅法 foo() 和 bar()。两者都实现了 foo(), 但是只有 B 实现了 bar() (bar() 在 A 中没有标记为抽象,因为没有⽅法体时默认为抽象)。因为 C 是⼀个实现了 A 的具体类,所以必须要重写 bar() 并实现这个抽象⽅法。
然⽽,如果我们从 A 和 B 派⽣ D,我们需要实现我们从多个接⼝继承的所有⽅法,并指明 D 应该如何实现它们。这⼀规则既适⽤于继承单个实现(bar())的⽅法也适⽤于继承多个实现(foo())的⽅法。