问题
I have a class with a constant defined for it. I then have a class method defined that accesses that class constant. This works fine. An example:
#! /usr/bin/env ruby
class NonInstantiableClass
Const = "hello, world!"
class << self
def shout_my_constant
puts Const.upcase
end
end
end
NonInstantiableClass.shout_my_constant
My problem arises in attempting to move this class method out to an external module, like so:
#! /usr/bin/env ruby
module CommonMethods
def shout_my_constant
puts Const.upcase
end
end
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
NonInstantiableClass.shout_my_constant
Ruby interprets the method as requesting a constant from the module, rather than the class:
line 5:in `shout_my_constant': uninitialized constant CommonMethods::Const (NameError)
So, what magic tricks do you fellows have to let the method access the class constant? Many thanks.
回答1:
This seems to work:
#! /usr/bin/env ruby
module CommonMethods
def shout_my_constant
puts self::Const.upcase
end
end
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
NonInstantiableClass.shout_my_constant
HTH
回答2:
Its probably worth noting that you don't need to include modules into a metaclass.
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
Ruby has the extend
keyword that effectively adds the modules interface to a class, e.g.
class NonInstantiableClass
Const = "hello, world!"
extend CommonMethods
end
You still need to ensure you're referencing the right constant using self::Const
or const_get
, but extend <module>
is the better way to add those methods to the class.
回答3:
The problem is, if you just write Const
it is evaluated on Module creation time. You have to use Module#const_get
instead like this: const_get(:Const)
. This is evaluated at runtime when the method is executed. So this happens in your class and not in your module.
来源:https://stackoverflow.com/questions/1897699/in-ruby-allowing-mixed-in-class-methods-access-to-class-constants