Function 科特林:我怎样才能创建一个;“静态”;可继承函数?

Function 科特林:我怎样才能创建一个;“静态”;可继承函数?,function,kotlin,Function,Kotlin,例如,我想在一个扩展了父类的子类上有一个函数example() Child.example() Parent.example() 第一种“明显”的方法是通过父对象的伴随对象来实现,但这不允许子对象的示例() 我尝试的第二种方法是在Parent.Companion上定义扩展函数,这很不方便,因为您必须定义一个Companion对象。它也不允许example()用于Child 有人知道我如何做到这一点吗?由于伴生对象与其他对象遵循相同的规则,因此很容易对它们使用常规的代码重用方法: open cl

例如,我想在一个扩展了父类的子类上有一个函数
example()

Child.example()
Parent.example()
第一种“明显”的方法是通过
父对象的伴随对象来实现,但这不允许
子对象的
示例()

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


有人知道我如何做到这一点吗?

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

open class Example {
    fun example() {}
}

class Parent {
    companion object : Example()
}

class Child {
    companion object : Example()
}

fun main(args: Array<String>) {
    Child.example()
    Parent.example()
}
其目的是为施工创造一个“替代运营商”

在Java中,当用作“构造函数”时,应该使用工厂而不是静态方法

在Kotlin方面,您可以使用顶级函数而不是工厂

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

您所要求的并不存在,您似乎在要求:

我可以从子类的类引用引用超类的伴生对象方法吗

或者你可能会问:

我可以从子类的引用引用超类的静态成员吗

两者的答案都是否定的。这是Kotlin的设计,这是不允许的,是一个有意识的决定,是故意的。如果你想改变这个决定,你需要。Java程序员对静态方法的继承和重写、从一个引用调用时的行为以及如何静态解析而不是动态解析感到非常困惑。Java8团队在向接口添加静态方法时意识到了这可能导致的混乱,因此他们采用了更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() 
    }
}
或作为扩展:

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

使静态函数可继承有什么意义?@DanielTran好吧,它不一定是“静态的”,因为它是Kotlin。其目的是为构造创建一个“替代操作符”,比如
Child[1,2,3]
而不是
Child(1,2,3)
@DanielTran例如,为子类强制工厂方法怎么样?有没有办法避免必须定义伴随对象?它可能是一个常规对象;)您提到的都是对的,但是子类不能使用它们。您是否错过了扩展函数的导入?当你导入静态扩展函数时,它应该在子类中可用。对不起,我应该用更好的措辞。我的意思是,您不能在子类中自动使用它们。与在名为
parent
的父对象的伴随对象中定义函数
example()
一样,将允许您执行
parent.example()
;对于名为
child
Parent
的子级,您无法自动执行
child.example()
。您是对的,它甚至不能使用静态扩展函数
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()