Consider the following (correct) Ruby program:
class Outer
Inner = Struct.new(:dummy) do
CONST = 'abce'
def fun
puts(dummy)
end
end
end
obj = Outer::Inner.new(15)
obj.fun
puts(Outer::CONST)
Why do I have to write Outer::CONST instead of Outer::Inner::CONST?
My understanding of the block passed to Struct::new was that self is bound to Outer::Inner, and indeed, we can see that the method (fun) is attached to the Inner class; but CONST obviously is not.
This happens because the constant is defined in the current namespace. The class and module keywords define namespaces, but Struct.new (just like Class.new) does not.
In order to define the constant under the Struct's scope, you have to use self::
class Outer
Inner = Struct.new(:dummy) do
self::CONST = 'abce'
end
end
Outer::Inner::CONST
#=> 'abce'
Outer::CONST
#=> NameError uninitialized constant Outer::CONST
After a little digging I was able to figure this out. Here's a quote from a similar question:
Constants belong to classes, therefore constant resolution via the :: operator only works with class objects.
In your above example Inner is a constant not a class, so Outer::Inner::CONST won't work. If we redefine Inner as a class we see the expected results.
class Outer
class Inner
CONST = 'abce'
Deeper = Struct.new(:dummy) do
def fun
puts(dummy)
end
end
end
end
obj = Outer::Inner::Deeper.new(15)
obj.fun
puts(Outer::Inner::CONST)
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