Circular references with vals in Kotlin

吃可爱长大的小学妹 提交于 2019-12-12 17:24:44

问题


In Kotlin, say I have data class A (val f: B) and data class B (val f: A). I want to initialize local var a: A and var b: B such that a.f is b and b.f is a. A.f and B.f must remain vals. Is this circular instantiation possible?

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 a.f == b and b.f == a ??
}

回答1:


Not exactly what you want but should work:

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
}

If you do not care about data class properties being vals, you can get rid of interfaces and use just implementation classes.




回答2:


Answered by Dmitry Jemerov on the kotlinlang Slack group:

The only possibility is to use reflection. Pass a dummy B instance to the constructor of A, then create a real instance of B passing the A instance as a parameter, and then use reflection to change the value of “f” field in the A instance to the B instance.

But I would strongly suggest you to not do that, and instead to reconsider your data model.




回答3:


Passing an object which is not constructed yet as argument seems to be impossible. So, I think such cross-reference initialization is not possible with original data classes.

But some workaround could be done though:

data class A(val f: A.() -> B)
data class B(val f: B.() -> A)

val A.b: B get() = f(this)
val B.a: 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 === b.a )
    require( b === a.b )
    require( b === b.a.b )
    require( a === a.b.a )

    println("Done.")
}


来源:https://stackoverflow.com/questions/35439421/circular-references-with-vals-in-kotlin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!