与Kotlin的vals循环引用

在Kotlin中,假设我有data class A (val f: B)data class B (val f: A) 。 我想初始化本地var a: Avar b: B ,使得afbbfaAfBf必须保持vals。 这个圆形实例化可能吗?

 data class A(val f: B) data class B(val f: A) fun foo() { var a: A var b: B // instantiate a and b here with af == b and bf == a ?? } 

    不完全是你想要但应该工作:

     interface A { val f: B } interface B { val f: A } data class AImpl(override var f: B) : A data class BImpl(override var f: A) : B fun <T> uninitialized(): T = null as T fun foo() { var aImpl = AImpl(uninitialized()) var bImpl = BImpl(aImpl) aImpl.f = bImpl val a: A = aImpl val b: B = bImpl } 

    如果你不关心数据类属性是val ,你可以去掉接口并使用实现类。

    由Dmitry Jemerov在kotlinlang Slack小组回答:

    唯一的可能是使用反射。 将一个虚拟的B实例传递给A的构造函数,然后创建一个B实例作为参数传递A实例,然后使用反射将A实例中的“f”字段的值更改为B实例。

    但是我强烈建议你不要那样做,而是要重新考虑你的数据模型。

    传递一个尚未构建的对象似乎是不可能的。 所以,我认为这种交叉引用初始化对于原始数据类是不可能的。

    但是,一些解决方法可以做到:

     data class A(val f: A.() -> B) data class B(val f: B.() -> A) val Ab: B get() = f(this) val Ba: A get() = f(this) fun test() { val O = object { val refA: A = A { refB } val refB: B = B { refA } } var a = O.refA var b = O.refB // validating cross-refs require( a === ba ) require( b === ab ) require( b === bab ) require( a === aba ) println("Done.") }