Kotlin - 如何使外部类只读字段

27

我在Android上有以下的Kotlin类:

class ThisApplication: Application() {

    lateinit var network: INetwork

    override fun onCreate() {

        super.onCreate()

        network = Network()
    }
}

现在,任何外部类都可以通过简单地执行以下操作来获取INetwork引用:

application.network

然而,这也使得外部类有可能覆盖该值:

application.network = myNewNetworkReference

我希望避免第二个选项。不幸的是,我无法创建val字段,因为它的初始化需要在onCreate回调函数内部进行。

我还考虑过将该字段设为私有,并通过函数进行公开,就像这样:

private lateinit var network: INetwork
fun getNetwork() = network

然而,调用getNetwork()的人仍然可以像这样给它赋一个新值:

application.getNetwork() = myNewNetworkReference

如何使网络字段被外部类只读?或者更好的方法是,有没有办法让它成为val,即使我无法在构造函数内初始化它?


调用方法的调用者不能重新分配该方法的值,application.getNetwork() = myNewNetworkReference 无法编译。 - yole
3个回答

45
为了限制外部类的访问,您可以更改访问器的可见性。对于您的情况,您需要使用lateinit修饰符的private setter和public getter:
lateinit var network: INetwork
    private set

或者是一个只读的延迟属性:

val network: INetwork by lazy { Network() }  //you can access private property here, eg. applicationContext

关于这段代码,你有一些误解:

private lateinit var network: INetwork
fun getNetwork() = network

Kotlin是像Java一样的值传递方式。因此,application.getNetwork() = myNewNetworkReference不是有效语句。我们不能将值分配给函数的返回值。


13
您可以单独修改getter/setter的可见性,与实际变量的可见性是独立的:
lateinit var network: INetwork
    private set

2

对于您的情况,val network: INetwork by lazy { ... }是否适用?

lambda表达式将在第一次引用字段network时调用。 显然,这与将初始化延迟到OnCreate方法不同,但它是一种使其成为val而无需在构造函数中初始化的方法。

还有其他委托选择。 值得查看Kotlin文档


这对于这个特定的情况可以工作,因为Network类不需要任何参数。谢谢。但是,我已经简化了示例。我需要一种依赖于onCreate的方法,因为有些实例需要一个已初始化的Context对象。例如,我可能会实例化一个SQLDatabase(this),它需要在onCreate中,因为我正在将“this”(Context)传递给它。 - Bitcoin Cash - ADA enthusiast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接