Kotlin 科特林:相互分配
我想设置两个值,它们彼此保持不可变的引用。例如:Kotlin 科特林:相互分配,kotlin,immutability,Kotlin,Immutability,我想设置两个值,它们彼此保持不可变的引用。例如: 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
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
由于多种原因,在此处使用数据类不起作用
:
数据类
不能有空构造函数java.lang.StackOverflowerError
失败。因此,您必须覆盖到字符串
,等于
,等等。哪种首先违背了使用数据类的目的
val
s(与java中的final
相同)这个是一个糟糕的想法。调用otherFactory
时,其参数仅初始化了一半。这可能会导致严重的错误,尤其是当您试图在多线程环境中发布此类引用时
更安全的方法是在第一个人的构造函数中创建两个人(您需要提供两个实体的字段作为参数)。它更安全,因为您可以控制使用半初始化此
引用的代码
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
(也就是说,它只是直接在其构造函数中给出)
思想最受欢迎。
可能是空值var。我真的希望避免可空变量。应用程序的其余部分在设置时应该考虑这个属性是不可变的。这是一个循环依赖问题:要创建杰克,我需要JIL,这又需要杰克等等。@ M0SKIT0纠正。有什么想法吗?@CSJ我想我没有正确解释自己。你想做的事情在逻辑上是不可能的(更严格地说,它需要无限的时间),除非你想放松你的条件。可能是lazy
或lateinit
?我在这里用lateinit
写的。虽然我可以将Person?
类型转换为Person
,但我觉得它不再可读了。更重要的是,我不确定当有并发访问时,isInitialized
检查会发生什么。