在其功能内返回对单例类实例的引用

时间:2019-12-07 10:15:07

标签: kotlin

在下面的代码中,我想设置对类实例的引用,以便静态函数可以返回对该实例的引用:

open class TestRunner {

    init {
        instance = this
    }

    companion object {
        private lateinit var instance: TestRunner

        fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner {
           for (setup in testSetups) {
              testsSetups.add(setup)
           }

           return instance
        }
    }
}

但是不允许设置instance = this。如何在保持类为单例状态的同时从函数返回该类的实例?

3 个答案:

答案 0 :(得分:0)

这似乎有效。代替保留一个变量来保存对该类的引用,只需引用该类的名称就足够了。但是,要从函数返回类的实例,返回类型必须为Companion:

open class TestRunner {
    companion object {
        fun addTestSetups(vararg testSetups: () -> TestSetup): Companion {
           for (setup in testSetups) {
              testsSetups.add(setup)
           }

           return TestRunner
        }
    }
}

这不是真正的单例,因为如果这样做,您仍然可以创建新实例:

val testRunner = TestRunner()

但是,如果您从不创建实例,而仅静态地引用函数,则它的行为就像单例一样,并且随行对象中任何私有变量的状态仍将保持。

更新

我在Android开发人员网站上遇到了这段代码,该代码显示了一个设置为单例的类的示例:

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private val stockManager: StockManager = StockManager(symbol)

    private val listener = { price: BigDecimal ->
        value = price
    }

    override fun onActive() {
        stockManager.requestPriceUpdates(listener)
    }

    override fun onInactive() {
        stockManager.removeUpdates(listener)
    }

    companion object {
        private lateinit var sInstance: StockLiveData

        @MainThread
        fun get(symbol: String): StockLiveData {
            sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
            return sInstance
        }
    }
}

但是应该指出的是,该示例需要一些函数,这些函数需要返回一个实例,以首先检查是否设置了实例变量,如果未设置,则创建一个新实例。我不确定这样做的目的是什么,因为调用已有实例的函数。那么,为什么还要创建一个新实例呢?似乎没有任何意义。

答案 1 :(得分:0)

如果我说对了,您想要这样的东西:

abstract class TestRunner {
    companion object : TestRunner()
}

答案 2 :(得分:0)

Kotlin中的

object是单例,而不是其内部定义的类。伴随对象具有额外的便利,允许您使用该外部类的名称来调用它。但是否则它不共享任何层次结构。

要使您的类可继承,您不能在伴随对象中定义函数。但是您可以将类抽象化,因此除非进行子类化,否则无法实例化该类。然后使您的伴随对象扩展抽象类,以便它将所有这些功能都可用。

abstract class TestRunner{
    open fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner{
        //...
        return this
    }

    companion object: TestRunner()
}

用法:

TestRunner.addTestSetups(someTestSetup)

请注意,您的单例不是TestRunner的实例。它是TestRunner子类的单例实例。但是,由于您没有定义任何额外的功能并且什么也没有覆盖,因此它的行为完全类似于TestRunner。

如果您想要一个子类:

abstract class ExtendedTestRunner: TestRunner() {

    fun someOtherFunction() {}

    companion object: ExtendedTestRunner()
}

同伴并没有被子类化,但是它们的抽象父母可以被归类。