I mean, I understand why this interaction works th...
# announcements
h
I mean, I understand why this interaction works this way, but it still makes me sad ☹️ https://pl.kotl.in/_g7Nag0rP in my particular use case, it'd be nice if the
Bar1
was also added to
foos
, but I imagine in other cases, that would be horrendous
r
What about that makes you sad?
h
i updated the message
r
Hm, why does the constructor of
Bar1
not throw? You can't do
'+=
on
null
h
oh, because foos hasn't been instantiated yet?
r
It looks like
Bar1
isn't actually instantiated till it's used:
Copy code
class EffectBuffer<P : Any>(val key: String, type: PaintType<P>) {
    val blend = ShaderProperty.dynamic(
        type.blendType,
        "Blend",
        "Blending Mode",
        type.defaultBlend
    )

    val shaders = mutableListOf<Shader<P>>()
}

abstract class Foo(val name: String = "Foo") {
    init {
        println("Instantiating $name")
        foos += this
        println(foos)
    }

    override fun toString() = name
}

object Bar1 : Foo("Bar1")

val foos = mutableListOf<Foo>()

fun main() {
    val bar2 = object : Foo("Bar2") {}
    foos.forEach(::println)
    println(Bar1.name)
}
s
foos
is not null. You can have forward declarations. Circular declarations may have some weird behavior, though.
h
hmm, that's actually really interesting
learning experience!
r
Indeed, that could be useful information.
s
If the ‘dependency’ tree is a-cyclical, Kotlin can figure out when to instantiate what vals/vars
Copy code
abstract class Base(val base: Base?, val id: Int) {
    init {
        println("Initing $base with id $id")
    }
}

object A: Base(B, 1)
object B: Base(A, 2)

fun main() {
    println("{$A.base} and ${B.base}")
}
Cyclical ; not sure if behavior is defined or undefined, but I guess you shouldn’t count on it 🙂
h
ah, good to know
r
Interesting, because this seems to work fine (neither
val
is
null
):
Copy code
object A {
    val b = B
}

object B {
    val a = A
}

fun main() {
    println(A.b)
    println(B.a)
}
s
But to your point, initialization is somewhat lazy: try
Copy code
abstract class Base(val base: Base?, val id: Int) {
    init {
        println("Initing $base with id $id")
    }
}

object A: Base(B, 1)
object B: Base(A, 2)

fun main() {
    println("Main")
    println("{$A.base} and ${B.base}")
}
You’ll see that
Main
is printed before the
Initing ..
ones
Copy code
Main
Initing null with id 2
Initing cycle.B@2c7b84de with id 1
{cycle.A@3fee733d.base} and null
👍 1
l
all you need to do is to use
Bar1
https://pl.kotl.in/z0dp394Jk
h
@Ruckus I think because when you call
println(A.b)
it instantiates A, which then calls B to set A.b, so now B is being instantiated, which then calls A to set B.a, which is already instantiated
🤔 1
💯 1
s
More evidence
object
initialization is a bit lazy.
👆 1
h
@louis993546 I guess this is a case for ping!
fun Any.ping() = this