例如:
class Animal
def make_noise
print NOISE
end
end
class Dog < Animal
NOISE = "bark"
end
d = Dog.new
d.make_noise # I want this to print "bark"
如何完成上述操作?目前它说
uninitialized constant Animal::NOISE
答案 0 :(得分:27)
我认为你真的不想要一个常数;我认为你想在类上有一个实例变量:
class Animal
@noise = "whaargarble"
class << self
attr_accessor :noise
end
def make_noise
puts self.class.noise
end
end
class Dog < Animal
@noise = "bark"
end
a = Animal.new
d = Dog.new
a.make_noise #=> "whaargarble"
d.make_noise #=> "bark"
Dog.noise = "WOOF"
d.make_noise #=> "WOOF"
a.make_noise #=> "whaargarble"
但是,如果您确定需要常量:
class Animal
def make_noise
puts self.class::NOISE
# or self.class.const_get(:NOISE)
end
end
答案 1 :(得分:5)
没有类实例变量的一种方法:
class Animal
def make_noise
print self.class::NOISE
end
end
class Dog < Animal
NOISE = "bark"
end
d = Dog.new
d.make_noise # prints bark
答案 2 :(得分:0)
我认为你的概念错了。 Ruby中的类与Java,Smalltalk,C#中的类类似,并且所有类都是其实例的模板。因此,类定义了结构和行为,如果它的实例,以及它的子类实例的结构和行为的部分但不是反之亦然。
因此,根本不可能从超类直接访问子类中的常量,这是一件好事。请参阅下文如何解决它。对于您定义的类,以下是正确的:
class Animal
定义方法make_noise
。class Animal
的实例可以调用方法make_noise
。class Dog
使用其值定义常量NOISE
。Dog
的实例和类Dog
本身可以使用常量NOISE
。什么是不可能的:
Animal
或类Animal
的实例本身可以访问类Dog
的常量。您可以通过以下更改来解决此问题:
class Animal
def make_noise
print Dog::NOISE
end
end
但这是不好的风格,因为现在,你的超类(它是关于Dog
和其他动物的抽象)现在知道属于Dog
的东西。
更好的解决方案是:
Animal
中定义一个抽象方法,该方法定义应定义make_noise
。请参阅答案https://stackoverflow.com/a/6792499/41540。答案 3 :(得分:0)
如果您正在执行此操作来配置子类,以便基类可以访问常量,那么您可以为它们创建DSL,如下所示:
module KlassConfig
def attr_config(attribute)
define_singleton_method(attribute) do |*args|
method_name = "config_#{attribute}"
define_singleton_method method_name do
args.first
end
define_method method_name do
args.first
end
end
end
end
class Animal
extend KlassConfig
attr_config :noise
def make_noise
puts config_noise
end
end
class Dog < Animal
noise 'bark'
end
这种方式更有效,因为在每个方法调用中,您都不必反省该类以返回(或者它是向前?)常量。
答案 4 :(得分:-1)
如果你想要面向对象的方式(TM),那么我想你想要:
class Animal
# abstract animals cannot make a noise
end
class Dog < Animal
def make_noise
print "bark"
end
end
class Cat < Animal
def make_noise
print "meow"
end
end
d = Dog.new
d.make_noise # prints bark
c = Cat.new
c.make_noise # prints meow
如果您想重构以防止重复print
的代码:
class Animal
def make_noise
print noise
end
end
class Dog < Animal
def noise
"bark"
end
end
class Cat < Animal
def noise
if friendly
"meow"
else
"hiss"
end
end
end
d = Dog.new
d.make_noise # prints bark
c = Cat.new
c.make_noise # prints meow or hiss