Kotlin:我如何创建一个“静态”可继承的函数?

例如,我想在扩展Parent的类型Child上有一个函数example() ,这样我就可以同时使用这个函数。

 Child.example() Parent.example() 

第一个“显而易见”的方法是通过Parent的伴侣对象,但是这不允许用于Child example()

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

有人知道我怎么能做到这一点?

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

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

或者你问:

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

两者的答案是否定的 。 这是Kotlin 的设计 ,这是不允许的,是一个有意识的决定,是故意的。 如果你想改变这个决定,你需要在YouTrack中提出问题 。 Java中的程序员对静态方法的继承和重写以及从一个引用与另一个引用进行调用时的行为以及如何静态解析而不是动态地解决了很大的困惑 。 Java 8团队在向接口添加静态方法时意识到这可能导致混淆,因此他们采取了更多的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() } } 

或作为扩展:

 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() 

由于伴侣对象按照与其他对象相同的规则进行操作,因此使用常规的代码重用方法很容易:

 open class Example { fun example() {} } class Parent { companion object : Example() } class Child { companion object : Example() } fun main(args: Array<String>) { Child.example() Parent.example() } 

另外,对于类委托,您可以直接重用Parent的实现:

 interface Example { fun example() } class Parent { companion object : Example { override fun example() {} } } class Child { companion object : Example by Parent.Companion } 

目的是建立一个“替代运营商”的建设

在Java中,当用作“构造函数”时,应该使用Factory来代替静态方法。

在Kotlin方面,您可以使用顶级功能而不是Factory。

或者如果你真的想在你的类中有一个“静态方法”,我会创建一个伴随对象并添加静态扩展方法。