Kotlin:我如何创建"静态"可继承功能?

Jir*_*ire 24 function kotlin

例如,我想example()在一个Child扩展的类型上有一个函数,Parent以便我可以在两者上使用该函数.

Child.example()
Parent.example()
Run Code Online (Sandbox Code Playgroud)

第一个"显而易见"的方法是通过同伴对象Parent,但这是不允许example()的Child.

我尝试的第二种方法是定义一个扩展函数Parent.Companion,这是不方便的,因为你被迫定义一个伴随对象.它也不允许example()对Child.

有人知道我怎么做吗?

Jay*_*ard 27

你要求的东西不存在,你似乎在问:

我可以从其后代的类引用中引用超类的伴随对象方法

或许你在问:

我可以从其后代的引用中引用超类的静态成员.

两者的答案都是否定的.它是由设计科特林的,这是不允许的,是一个非常明智的决定,是故意的.如果您希望更改此决定,则需要在YouTrack中提交问题.Java中的程序员很容易被静态方法的继承和覆盖以及从一个引用与另一个引用调用时的行为以及如何静态解析而不是动态地混淆.Java 8团队在向接口添加静态方法时实现了这可能造成的混乱,因此他们采用了更多的Kotlin方法,只允许接口引用调用它.为了避免这些类型的噩梦,Kotlin团队不允许这样做.就像他们不允许Java的许多其他令人困惑的方面一样.

其他答案(例如@voddan)通过使用伴侣对象给你解决方法来调用语法,但是你拒绝那些伴随对象,即使你的问题声明了你正在尝试使用它们.所以假设你不想使用它们,答案就是不,不能做到.

要摆脱伴侣对象,你想谈谈可以用"静态"方式调用扩展函数吗?......由于尚未被允许,这将令人失望.

回到伴侣对象(对不起,但它们是通往这里的荣耀之路),您也可以手动将子方法委托给父级:

open class Parent {
    companion object { // required, sorry, no way around it!
        fun foo() = /* some cool logic here */
    }
}

class Child: Parent() {
    companion object {  // required, sorry, no way around it!
        fun foo() = Parent.foo() 
    }
}
Run Code Online (Sandbox Code Playgroud)

或作为扩展:

open class Parent {
    companion object {} // required, sorry, no way around it!
}

class Child: Parent() {
    companion object {} // required, sorry, no way around it!
}

fun Parent.Companion.foo() = /* some cool logic here */
fun Child.Companion.foo() = Parent.foo()
Run Code Online (Sandbox Code Playgroud)


vod*_*dan 15

由于伴随对象遵循与其他对象相同的规则,因此很容易在它们上使用正常的代码重用方法:

open class Example {
    fun example() {}
}

class Parent {
    companion object : Example()
}

class Child {
    companion object : Example()
}

fun main(args: Array<String>) {
    Child.example()
    Parent.example()
}
Run Code Online (Sandbox Code Playgroud)

或者使用类授权,您可以Parent直接重用实现:

interface Example {
    fun example()
}

class Parent {
    companion object : Example {
        override fun example() {}
    }
}

class Child {
    companion object : Example by Parent.Companion
}
Run Code Online (Sandbox Code Playgroud)