Let’s say we have two classes, Foo and Foo Sub, each in a different file, foo.rb and foo_sub.rb respectively.
foo.rb:
require 'foo_sub' class Foo def foo FooSub.SOME_CONSTANT end end
foo_sub.rb:
require 'foo' class FooSub < Foo SOME_CONSTANT = 1 end
This isn’t going to work due to the circular dependency – we can’t define either class without the other. There are various solutions that I’ve seen. Two of them I want to avoid – namely, putting them in the same file and removing the circular dependency. So, the only other solution I’ve found is a forward declaration:
foo.rb:
class Foo end require 'foo_sub' class Foo def foo FooSub.SOME_CONSTANT end end
foo_sub.rb
require 'foo' class FooSub < Foo SOME_CONSTANT = 1 end
Unfortunately, I can’t get the same thing to work if I have three files:
foo.rb:
class Foo end require 'foo_sub_sub' class Foo def foo FooSubSub.SOME_CONSTANT end end
foo_sub.rb:
require 'foo' class FooSub < Foo end
foo_sub_sub.rb:
require 'foo_sub' class FooSubSub < FooSub SOME_CONSTANT = 1 end
If I require foo_sub.rb, then FooSub is an uninitialized constant in foo_sub_sub.rb. Any ideas how to get around this without putting them in the same file nor removing the circular dependency?
If you need to access a subclass from a superclass then there’s a good chance that your model is broken (i.e. it should be one class).
That said, there are a couple of obvious solutions:
1) just create a file that requires the foo files:
all_foos.rb:
and remove the requires from foo.rb and foo_sub.rb.
2) remove the require from foo.rb
3) remove the require from foo_sub.rb and put the require in foo.rb after the class definition.
Ruby isn’t C++, it won’t complain about FooSub.SOME_CONSTANT until you call Foo#foo() 😉