[英]Kotlin lazy initialization in subclass
我正在嘗試使用在子類中初始化的屬性構建字符串。
我讀到了關於延遲初始化的信息,但是以某種方式無法正常工作。
abstract class SubProcessFullNameBuilder(technicalDomain: TechnicalDomainEnumeration) {
protected val moduleName = "td.${technicalDomain.value().toLowerCase()}.shared"
private val packageName by lazy { packageName() }
private val processName by lazy { processName() }
val processFullName: String = "$moduleName/$packageName.$processName"
protected abstract fun packageName(): String
protected abstract fun processName(): String
}
class WorkerFullNameBuilder(
private val jmsDirection: JmsDirectionEnumeration,
technicalDomain: TechnicalDomainEnumeration,
private val cdmCode: String) : SubProcessFullNameBuilder(technicalDomain) {
override fun packageName() = "$moduleName.workers.${jmsDirection.value().toLowerCase()}.${cdmCode.toLowerCase()}"
override fun processName() = "Worker"
}
由於我重寫了packageName()
和processName()
屬性,因此我希望在調用packageName
屬性時,它將使用子類中的實現。
但是,當我調用processFullName
屬性時,它將引發java.lang.NullPointerException
。
val builder = WorkerFullNameBuilder(JmsDirectionEnumeration.ESB_IN, TechnicalDomainEnumeration.INFOR, "ccmd")
val name = builder.processFullName
如何以適當的方式初始化packageName和processName屬性?
這是在構造函數中調用非最終方法並因此訪問未初始化的變量的情況。
在構造基類時,仍會急切地評估此行:
val processFullName: String = "$moduleName/$packageName.$processName"
要獲取這兩個惰性屬性的值,將調用抽象方法,其中packageName()
引用jmsDirection
和cdmCode
返回其值-這些屬性尚未初始化,因為它們的值是在超類構造函數之后設置的運行。 這是子類的構造函數的簡化版本,已反編譯回Java:
public WorkerFullNameBuilder(@NotNull JmsDirectionEnumeration jmsDirection, @NotNull TechnicalDomainEnumeration technicalDomain, @NotNull String cdmCode) {
super(technicalDomain);
this.jmsDirection = jmsDirection;
this.cdmCode = cdmCode;
}
作為演示,例如,如果您不引用它們,例如,如果您在兩個子類方法中都返回常量,則您的代碼實際上可以正常運行:
override fun packageName() = "foo"
override fun processName() = "Worker"
但是,您這里需要的解決方案最有可能使processFullName
屬性本身成為惰性的,而不是它使用的兩個值(無論如何,您現在正在構造函數時對其進行評估,因此您不會利用它們是惰性的)。 這意味着您甚至不需要將這兩個屬性作為單獨的屬性:
abstract class SubProcessFullNameBuilder(technicalDomain: TechnicalDomainEnumeration) {
protected val moduleName = "td.${technicalDomain.value().toLowerCase()}.shared"
val processFullName by lazy { "$moduleName/${packageName()}.${processName()}" }
protected abstract fun packageName(): String
protected abstract fun processName(): String
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.