Following code is just a simple simulation, the really code is more complex, even recursively, make set @root value directly in initialize is almost not possible.
@root : String
# here we have complicated logic to ensure @root is exists before use it.
@root = "/home"
a = A.new
Error: instance variable '@root' of A was not initialized directly in all of the 'initialize' methods, rendering it nilable. Indirect initialization is not supported.
A workaround I’ve used is to change your @root : String to @root = uninitialized String. When I run your code using that, it is happy.
Assuming there’s some reason you can’t directly set
@root = "/home" in the initialize method, you could turn
calculate into a macro instead, and have that code embedded into your initialize call instead?
Another option would be to turn the type of
String? instead, and then define a custom getter that only returns
String and use that in your code instead of
@root directly. i.e.:
@root : String? = nil
private def root
@root || raise "Root is nil! This shouldn't be called, unless calculate has a bug because it's overly complicated"
# use `root` instead of `@root` here
def root private.
@root = calculate
Yes, in fact, I did use this solution.