[英]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.