inheritancekotlinandroid-roomkotlin-companion

Companion object method not accessible from subclass


I'm trying to use the method getInstance from a subclass.
Any idea why the mentioned method is unaccessible and how to change this code so i can access it?

For the curious mind, this example structure comes from trying to subclass a Room database class on Android.

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 ??
    }
}

the SingletonHolder class is derived from the lazy implementation in kotlin and allows passing an argument to the creator function. https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e

superclass is mimicking abstract class MyRoomDatabase : RoomDatabase() on Android, this will create an instance of a sqlite db at runtime and is suggested to be implemented as singleton. This is in my case inside a service. superclass_Impl will be created by the Room Library.

subclass is in my case a subclass of MyRoomDatabase and lives on the client that will connect to the service. I'm trying to extend it to add query methods used only by the client. subclass_Impl will be created by the Room Library.


Solution

  • Clearly you are thinking static members are inherited in java and since companion objects are the same thing, I should be able to the following.

    subclass.getInstance() // as in question, subclass is name of the class not its instance
    

    Sorry, this is not allowed. Companion objects are not java's static members. Kotlin is designed to be a language where you don't need such constructs. So don't try to write java code using kotlin features.

    if you want to refer a comapnion object member as you refer to java's static members, then you must specify the name of containing class of companion object. In your case

    superclass.getInstance(1).f2()