1

Let's assume a simple class:

class Foo(val p:String)

I would like to create instance of the class by passing lazy delegate:

val lazyP by lazy {"foo"}
println(Foo(lazyP).p)

but I don't need the boilerplate lazyP variable. How to write a one-liner? Something like:

println(Foo(by lazy {"foo"}).p)
Maciej Sz
  • 11,151
  • 7
  • 40
  • 56

1 Answers1

1

I presume what you're trying to do is construct Foo and have p only calculated when it's first called? If so, I don't think that defining Foo as you've done will work, because when you construct Foo, the lazy delegate is called. That's because in order to construct Foo, a string is needed, so the lazy delegate is evaluated at that point. In other words, this:

val lazyP by lazy { "foo" }
val foo = Foo(lazyP)

is more-or-less equivalent to:

val foo = Foo("foo")

I think that if you want Foo to have a lazy delegated property you should define it like this:

class Foo(lazyP: Lazy<String>) {
    val p by lazyP
}

Then you can construct it in a one-liner without needing a separate variable:

val foo = Foo(lazy { "foo" })
Yoni Gibbs
  • 6,518
  • 2
  • 24
  • 37
  • Ok, thats neat. But how can I make this lazy if I can't change the `Foo` class? – Maciej Sz Jan 09 '19 at 13:54
  • Good question :-) Are you able to change the client of `Foo` so that it doesn't use `Foo` directly, and instead uses some class you write which wraps or subclasses `Foo`? – Yoni Gibbs Jan 09 '19 at 14:12
  • Well, in this case, yes. But I imagine that wrapper isn't the cleanest solution. I wish the Kotlin compiler would generate inline lambda in places where `val p` is used. – Maciej Sz Jan 09 '19 at 15:30