Kotlin 中一个类和一个接口的多重继承

mou*_*sou 4 kotlin

我的预期目标是通过一组固定的属性和方法(其名称不会重叠)从现有库中扩展多个类。

直接的解决方案是简单的继承:派生库类并添加属性/方法。但这将是非常重复的,因为所有派生类的属性和方法都相同。最好创建一个包含我需要的所有属性和方法的辅助类,并简单地从库类和辅助类派生扩展类。

但是,由于 Kotlin 中似乎没有可与 C++ 相比的多重继承,我想使用接口使其工作,其中接口将包含我需要的所有属性和方法。

我已经开始使用以下简单的代码来测试接口:

open class LibraryClass{
    var x: Int = 0

    fun setMyX(x_: Int){
        x = x_
    }
}

interface MyInterface{
    var y: Int
    var z: Int
    var abc: Int

    fun myMethod(y_: Int){
        y = y_
        z = y*y
    }
} 

class InheritanceTest: LibraryClass(), MyInterface{    
    fun print(){
    println("My values: $x, $y, $z")
    }
}

fun main(){
    var test = InheritanceTest()
    test.setMyX(1)
    test.myMethod(5)
    test.print()    
}
Run Code Online (Sandbox Code Playgroud)

如果我尝试编译此代码,则会收到以下错误消息:

error: class 'InheritanceTest' is not abstract and does not implement abstract member public abstract var y: Int defined in MyInterface
Run Code Online (Sandbox Code Playgroud)

一些研究表明,我需要在派生类的主构造函数中覆盖接口的属性:

class InheritanceTest(override var y: Int, override var z: Int, override var abc: Int)
Run Code Online (Sandbox Code Playgroud)

进而

var test = InheritanceTest(2,3,0)
Run Code Online (Sandbox Code Playgroud)

在派生类中覆盖所有(?)接口属性(甚至未使用的)似乎非常重复(并且也不可能在接口中初始化属性),这基本上违背了我最初打算使用接口的目的:节省重复. (除了方法,只要一个类和(多个)接口不共享同名方法,这些方法似乎不必被覆盖)。

我提出的问题是:这是唯一的方法还是解决错误?

然后我在界面中找到了其他可以尝试的东西:

var fgh: Int 
    get()  { return fgh }
    set(v) { fgh = v }
Run Code Online (Sandbox Code Playgroud)

到目前为止不需要覆盖。但是我还不知道如何在方法中或通过设置值来实际使用属性 fgh。

当我尝试通过test.fgh = 100in设置 fgh时main(),出现以下错误:

Exception in thread "main" java.lang.StackOverflowError
    at MyInterface$DefaultImpls.setFgh(
Run Code Online (Sandbox Code Playgroud)

然后尝试使用test.setFgh(100)(因为之前的错误消息暗示该方法存在)产生:

error: unresolved reference: setFgh
Run Code Online (Sandbox Code Playgroud)

试图定义setFgh(v: Int) {fgh = v} 结果:

error: platform declaration clash: The following declarations have the same JVM signature (setFgh(I)V):
    fun <set-fgh>(v: Int): Unit defined in MyInterface
    fun setFgh(v: Int): Unit defined in MyInterface
Run Code Online (Sandbox Code Playgroud)

好的,定义一个不同命名的方法,类似于myMethod()

fun myOtherMethod(v: Int){    
    fgh = v 
    z = fgh * fgh
}
Run Code Online (Sandbox Code Playgroud)

然后再次使用myOtherMethod(10)inmain()给出:

Exception in thread "main" java.lang.StackOverflowError
    at MyInterface$DefaultImpls.setFgh
Run Code Online (Sandbox Code Playgroud)

所以,我现在真的不知道该怎么做才能获得一个非重复的工作解决方案来扩展具有相同属性和方法的多个类。

编辑:我现在明白接口并不是我想要的,因为必须实现派生类中的所有内容(不是覆盖,这花了我一段时间才能通过关键字“覆盖”完成)。

psh*_*ger 5

您第一次尝试就走对了。您确实必须覆盖接口中的属性,但不必在构造函数中完成。您可以在类主体中执行此操作,这样您就可以为它们添加默认值(不仅可以,而且必须)。如果您打开该类,则可以在所有类中扩展它。

open class InheritanceTest: LibraryClass(), MyInterface {
    override var y: Int = 0
    override var z: Int = 0
    override var abc: Int = 0

    fun print() {
        println("My values: $x, $y, $z")
    }
}
Run Code Online (Sandbox Code Playgroud)

使用这个类,您的原始 main 将 print My values: 1, 5, 25,并且您将能够从该类继承而无需覆盖/初始化任何内容(但您可以使用该init块来自定义您的超类)。例如:

class MyClass : InheritanceTest() {
    init {
        myMethod(4)
    }
}

fun main() {
    val test = MyClass()
    test.setMyX(2)
    test.print()
}
Run Code Online (Sandbox Code Playgroud)

将打印 My values: 2, 4, 16

我希望我正确理解了您的问题并可以提供帮助:)