Inheritance 无法从子类访问伴生对象方法

Inheritance 无法从子类访问伴生对象方法,inheritance,kotlin,android-room,kotlin-companion,Inheritance,Kotlin,Android Room,Kotlin Companion,我试图使用子类中的方法getInstance。 你知道为什么提到的方法是不可访问的,以及如何更改此代码以便我可以访问它吗 对于好奇的人来说,这个示例结构来自于尝试在Android上对Room数据库类进行子类化 open class SingletonHolder<out T: Any, in A>(creator: (A) -> T) { private var creator: ((A) -> T)? = creator @Volatile privat

我试图使用子类中的方法
getInstance

你知道为什么提到的方法是不可访问的,以及如何更改此代码以便我可以访问它吗

对于好奇的人来说,这个示例结构来自于尝试在Android上对Room数据库类进行子类化

open class SingletonHolder<out T: Any, in A>(creator: (A) -> T) {
    private var creator: ((A) -> T)? = creator
    @Volatile private var instance: T? = null

    fun getInstance(arg: A): T {
        val i = instance
        if (i != null) {
            return i
        }

        return synchronized(this) {
            val i2 = instance
            if (i2 != null) {
                i2
            } else {
                val created = creator!!(arg)
                instance = created
                creator = null
                created
            }
        }
    }
}

abstract class subclass(val par: Int): superclass(par) {
    abstract fun function1()
}

class subclass_Impl(val par1: Int): subclass(par1) {
    override fun function1() {
        Log.d("unused", "unused")
    }

    override fun f2() {
        Log.d("this is", "subclass Impl")
    }
}

abstract class superclass(val dummy: Int) {
    abstract fun f2()

    companion object : SingletonHolder<superclass, Int>( { Builder.build(it) } )
}

class superclass_Impl(val par: Int): superclass(par) {
    override fun f2() {
        Log.d("this is", "superclass_Impl")
    }
}

class Builder {
    companion object {
        fun build(par: Int): superclass_Impl {
            return superclass_Impl(par)
        }
    }
}

class test {
    fun test1() {
        superclass.getInstance(1).f2()
        subclass.getInstance(1).f2()  // getInstance is not visible ??
    }
}
开放类单音持有人(创建者:(A)->T){
私有变量创建者:((A)->T)?=创建者
@易失性私有变量实例:T?=null
fun getInstance(arg:A):T{
val i=实例
如果(i!=null){
返回i
}
返回已同步(此){
val i2=实例
如果(i2!=null){
i2
}否则{
val created=creator!!(arg)
实例=已创建
creator=null
创建
}
}
}
}
抽象类子类(val par:Int):超类(par){
抽象函数1()
}
类subclass_Impl(val par1:Int):子类(par1){
覆盖函数1(){
日志d(“未使用”、“未使用”)
}
覆盖f2(){
Log.d(“这是”“子类Impl”)
}
}
抽象类超类(val-dummy:Int){
抽象概念f2()
伴随对象:SingletonHolder({Builder.build(it)})
}
类超类(val par:Int):超类(par){
覆盖f2(){
Log.d(“这是”、“超类Impl”)
}
}
类生成器{
伴星{
有趣的构建(par:Int):超类{
返回超类_Impl(par)
}
}
}
课堂测试{
趣味测试1(){
超类.getInstance(1).f2()
子类.getInstance(1).f2()//getInstance不可见??
}
}
SingletonHolder
类派生自kotlin中的惰性实现,允许将参数传递给creator函数

superclass
在Android上模仿了
抽象类MyRoomDatabase:RoomDatabase()
,这将在运行时创建sqlite db的实例,建议将其实现为singleton。这是在我的情况下在一个服务<代码>超类\u Impl将由文件室库创建


subclass
在我的例子中是
MyRoomDatabase
的一个子类,它位于将连接到服务的客户端上。我试图扩展它以添加仅由客户端使用的查询方法<代码>子类\u Impl将由文件室库创建。

很明显,您认为静态成员是在java中继承的,因为伴随对象是相同的,所以我应该能够做到以下几点

subclass.getInstance() // as in question, subclass is name of the class not its instance
对不起,这是不允许的。伴随对象不是java的静态成员。Kotlin被设计成一种不需要这种构造的语言。因此,不要试图使用kotlin特性编写java代码

如果希望在引用java的静态成员时引用Comapion对象成员,则必须指定包含伴生对象的类的名称。就你而言

superclass.getInstance(1).f2()

很明显,您认为静态成员是在java中继承的,因为伴生对象是相同的,所以我应该能够做到以下几点

subclass.getInstance() // as in question, subclass is name of the class not its instance
对不起,这是不允许的。伴随对象不是java的静态成员。Kotlin被设计成一种不需要这种构造的语言。因此,不要试图使用kotlin特性编写java代码

如果希望在引用java的静态成员时引用Comapion对象成员,则必须指定包含伴生对象的类的名称。就你而言

superclass.getInstance(1).f2()

谢谢您的回答,正如您所说,我假设它在Java中是静态的。据我所知,根据文档,同伴实际上是单例变量,而不是静态变量。尽管如此,这里显示的行为似乎与
子类是超类的断言相矛盾。如果子类是一个超类,我应该能够调用
subclass.getInstance(1)
,并且应该能够在任何可以使用超类的地方使用子类。该断言通常仅适用于对象。例如,如果您看到,这显然意味着子类型的对象应该能够填充超类型对象。在您的例子中没有对象。请注意“a”:“子类是超类”。这是“子类的任何实例都是超类的实例”的缩写。类的伴随对象不是它们的实例。谢谢你的回答,正如你所说的,我假设它在Java中是静态的。据我所知,根据文档,同伴实际上是单例变量,而不是静态变量。尽管如此,这里显示的行为似乎与
子类是超类的断言相矛盾。如果子类是一个超类,我应该能够调用
subclass.getInstance(1)
,并且应该能够在任何可以使用超类的地方使用子类。该断言通常仅适用于对象。例如,如果您看到,这显然意味着子类型的对象应该能够填充超类型对象。在您的例子中没有对象。请注意“a”:“子类是超类”。这是“子类的任何实例都是超类的实例”的缩写。类的伴随对象不是它们的实例。在回答您的问题“如何更改此代码以便访问它”时,阅读了您链接的文章后,我认为解决方案是:不要创建超类”(文章中的Manager)一个你从中继承的类,但它是你使用的具体类。他们的解决方案已经非常复杂,添加层次结构会使问题变得更糟,正如你所展示的,在回答你的问题“如何更改此代码以便我可以访问它”时,它会停止工作“,阅读了您链接的文章后,我认为解决方案是:不要让超类(文章中的管理器)成为您继承的类,而是将其作为您使用的具体类。他们的解决方案已经非常复杂,添加层次结构会使其更糟,正如您所示