How to workaround `Indirect initialization is not supported.` issue?

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.

class A
  @root : String

  def initialize
    calculate
  end

  def calculate
   # here we have complicated logic to ensure @root is exists before use it.
    @root = "/home"
  end
end

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.

2 Likes

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 @root into 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"
end

def my_recursive_method(...)
   # use `root` instead of `@root` here
end

[EDIT] made def root private.

1 Like

Another way:

def initialize
  @root = calculate
end
2 Likes

Good ideas, thanks.

1 Like

Yes, in fact, I did use this solution. :grin:

1 Like