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