As I'm reading different Ruby books, I've noticed that Ruby classes can be defined within other Ruby classes or modules. Here's an example of a class within a class:
class Outerclass def foobar puts "FOOBAR" end class Innerclass def barfoo puts "BARFOO" end end end
Here's some code that I ran in IRB to try to understand this conceptually:
oc = Outerclass.new # => #<Outerclass:0x00000100a46478> Outerclass.instance_methods(false) # => [:foobar] ic = Outerclass::Innerclass.new # => #<Outerclass::Innerclass:0x00000100a0b120> ic = Outerclass::Innerclass.instance_methods(false) # => [:barfoo]
Here are my questions:
When the ruby interpreter first encounters my Class definition code above, does it go through the methods I've written and store it somewhere? I know that the instance method "foobar" doesn't actually get run since there's no call being made to it within the Outerclass definition.
Piggybacking off the 1st question, what about when Ruby encounters the class Innerclass? What happens here?
In general, what are some reasons why you would want to have classes within classes? Are there any advantages to doing this?
Does an instance of Outerclass know anything about the class Innerclass?
Does an instance of Innerclass know anything about the class Outerclass?
Appreciate any help you can provide!
What is the difference between a class and a module? Modules are collections of methods and constants. They cannot generate instances. Classes may generate instances (objects), and have per-instance state (instance variables).
No, you can't instantiate a module inside a class. Module are static objects that are instantiated before time 0 during elaboration.
Nesting class definitions in Ruby is a matter of preference, but it serves a purpose in the sense that it more strongly enforces a contract between the two classes and in doing so conveys more information about them and their uses. But to the Ruby interpreter, it's only a difference in name.
A Ruby module can contain classes and other modules, which means you can use it as a namespace.
When the interpreter is going through this file, it is assigning classes like this:
OuterClass = Class.new do def foobar puts "FOOBAR" end InnerClass = Class.new do def barfoo puts "BARFOO" end end end
So when Ruby encounters the nested class, it assigns it to constant InnerClass
which is assigned to constant OuterClass
They have no relation to each other whatsoever.
The InnerClass
has no inheritance to OuterClass
:
InnerClass.ancestors => [InnerClass, Object, Kernel, BasicObject]
When you call OuterClass::InnerClass
constant you are refering to the InnerClass
constant that is namespaced under the OuterClass
contstant which equals the Class.new statement assigned to it.
A good book to read about this is "Metaprogramming Ruby". It goes into the details of classes, singletons, modules etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With