Kotlin接口

本文深入探讨Kotlin中的接口概念,包括定义、实现、属性、多继承冲突解决及属性使用问题。详细介绍了Kotlin接口与Java接口的相似之处,以及如何在类中实现接口中的抽象方法和已实现的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述

Kotlin接口即可以有抽象方法,也可以有实现了的方法。接口与抽象类的区别在于接口不能存在状态。接口还可以有属性,不过这些属性只能是抽象的,或者提供访问器的实现。Kotlin的接口与Java的类似,也是可以多继承的。
接下来我们来看年Kotlin如何定义接口,以及多继承情况下如何解决冲突和Kotlin中的属性有何特别。

2.定义

Kotlin接口与Java接口定义一样也是用interface 关键字定义。接口中的方法可以是抽象或已实现了的,如:

interface MyInterface{
	fun bar()
	fun foo(){
		// optional body	
	}
}		

2.接口实现

类或对象都可以实现一个或多个接口。对象我们以后再讨论。现在来看类是如何实现接口的,类只需要实现抽象的方法即可:

class Child: MyInterface{
	override fun bar(){
		// body
	}
}

3.接口中的属性

你可以在接口中定义属性。接口中声明的属性可以是抽象的,或者它提供访问器的实现。在接口在声明的属性不能有返回字段(backing field),因此在接口中声明的访问器不能引用它们。

interface MyInterface{
	val prop:Int // 抽象的
	val propertyWithImplementation: String
		get() = "foo"  // 提供访问器实现
	fun foo(){
		print(prop)
	}
}
class Child: MyInterface{
	override val prop:Int = 29
}

4.多继承产生的冲突

类是可以继承多个接口的,但是这些接口都有相同方法的实现,那么就会造成引用冲突,可以使用super<接口名>.的方式,明确调用哪个接口里实现的方法,这样就不会产生歧义。

interface A {
    fun foo(){// 已实现的
        Log.i("Man","A")
    }
    fun bar() // 抽象的
}
package com.example.demo

import android.util.Log

interface B {
    fun foo(){// 已实现的
        Log.i("Man","B")
    }
    fun bar(){// 已实现的
        Log.i("Man","Bar")
    }
}

// D继承了接口A、B
class D:A,B {
    override fun foo() {
        super<A>.foo()
        super<B>.foo()
    }

    override fun bar() {
        super.bar()
    }
}

接口A、B实现了foo()方法,因此D实例调用这个方法时,一定会引发冲突,所以Kotlin要求子类必须重新实现这个方法。当D实例再调用时就是调自己的,就不会引发歧义了。如果要调用接口中那些实现了的方法,如果使用关键字super加限定词(就是接口名)。如果所示。

如果两个接口有同名的方法,如上例中的bar(),一个实现了,另一个没有实现的情况,就不会造成冲突,如果要调用那个在接口中已实现的方法,直接用super就可以,不需要加限定词,加了还会提示你说多余呢。为什么不用呢?因为只有一个接口实现了,引用不会存在歧义。

5.属性的使用问题

接口中的属性不能有初始化器,说白了就是不能初始化,如下面就是报错的:

interface A {
    var age: Int = 44 // 错误!错误!错误!属性的初始化器不能出现在接口中
    }

顺便说一句,初始化器就是等号右边的表达式。接口中的属性可以有访问器,即gettersetter,但是它们不能使用返回字段field:

interface A {

    var age: Int
        set(value){
            field = 9999  // 错误!错误!错误! field这个字段在接口中是不可用的
        }
        var count: Int
    	get() = 999  // 错误!错误!错误! field这个字段在接口中是不可用的,正常情况,get会有field字段返回的

    // 以下这个是OK的,子类都无须再实现这个属性,同时这个属性也不能再赋新值,因为field字段在此处不能用,goods永远是666
    var goods: Int
        get() = 666
        set(value) {}

 }

实现接口的属性有两个方法,一是直接赋值,即用初始器,二定义访问器settergetter:

interface A {
    var age: Int
}

class D:A {
    override var age: Int
        get() = 5
        set(value) {} // 没有返回字段field,因此不用初始化器
}
或者
class D:A {
	// 使用默认的setter/getter
    override var age: Int = 8
 }

// 如果setter方法有返回字段field,那么必须用初始化器
class D:A {
    override var age: Int = 8
    set(value){
    	field = value+1
    	}
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值