[英]Kotlin: Mutual assignments
我想設置兩個值,彼此保持不可變的引用。 例:
data class Person(val other: Person)
val jack = Person(jill), jill = Person(jack) // doesn't compile
注意: lateinit
似乎不適用於數據類主構造函數。
有任何想法嗎?
你可以逃避這樣的事情:
class Person() {
private var _other: Person? = null
private constructor(_other: Person? = null) : this() {
this._other = _other
}
val other: Person
get() {
if (_other == null) {
_other = Person(this)
}
return _other ?: throw AssertionError("Set to null by another thread")
}
}
然后你就能做到:
val jack = Person()
val jill = jack.other
在這里使用data class
不會出於多種原因 :
首先是因為data class
不能有空構造函數。
即使這不是問題,生成的方法最終會產生循環依賴,並且會在運行時因java.lang.StackOverflowError
而失敗。 所以你必須覆蓋toString
, equals
等,這首先打破了使用data class
的目的 。
這是訣竅(注意,這真的是一個技巧,你需要一個很好的理由在實際代碼中使用它)。
不幸的是,它不適用於數據類,因為它們似乎可以抵御這種黑客攻擊。
但是如果你有java-stile類,你可以使用兩件事:
val
(與java中的final
相同) this
構造函數中的(並且可能泄漏到外部,如果你真的想) 這意味着您可以在第一個人的構造函數內創建另一個Person
,並在構造函數完成之前完成兩個類的創建。
再一次:暴露this
就像我在下面做的那樣是一個壞主意。 當otherFactory
,它的參數只是半初始化。 這可能會導致令人討厭的錯誤,特別是如果您嘗試在多線程環境中發布此類引用。
更安全的方法是在第一個Person的構造函數內創建兩個Persons(您需要提供兩個實體的字段作為參數)。 它更安全,因為您可以控制使用半初始化this
引用的代碼。
class Person {
val name: String
val other: Person
constructor(name: String, other: Person) {
this.name = name
this.other = other
}
// !! not very safe !!
constructor(name: String, otherFactory: (Person) -> Person) {
this.other = otherFactory(this)
this.name = name
}
// a bit safer
constructor(name: String, otherName: String) {
this.other = Person(otherName, this)
this.name = name
}
}
val person1 = Person("first") {
Person("second", it)
}
val person2 = person1.other
print(person1.name) // first
print(person2.name) // second
val person3 = Person("third", "fourth")
val person4 = person3.other
print(person3.name)
print(person4.name)
感謝大家的建議。 我提出了一個替代方案,並希望聽到您的見解:
open class Person {
open val other: Person by lazy { Person2(this) }
class Person2(override val other: Person): Person()
}
val jack = Person()
val jill = jack.other
在這里,我們沒有一個人懶洋洋地實例化的其他需求,使用實現內部子類other
不同的(也就是說,它只是給它直接在它的構造函數)。
最受歡迎的想法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.