假设我有一个带有一些“静态”变量的类。我希望该类的子类能够覆盖这些变量而不会影响原始类。使用类变量是不可能的,因为它们似乎在子类和超类之间共享:
class Foo
@@test = "a"
def speak; puts @@test; end
end
class Bar < Foo
@@test = "b"
end
Bar.new.speak
# b
Foo.new.speak
# b
使用常量也是不可能的:
class Foo
TEST = "a"
def speak; puts TEST; end
end
class Bar < Foo
TEST = "b"
end
Bar.new.speak
# a
Foo.new.speak
# a
超类中定义的方法忽略子类中的常量。
明显的解决方法是为需要“可覆盖”的变量定义方法:
class Foo
def test; "a"; end
end
但这感觉就像是黑客。我觉得这应该可以使用类变量,我可能只是做错了。例如,当我将Object
子类化时(默认情况下会发生这种情况):
class Foo < Object
@@bar = 123
end
Object.class_variable_get(:@@bar)
# NameError: uninitialized class variable @@bar in Object
为什么@@bar
上的Object
设置不像我上面的Bar < Foo
示例中那样?
总结一下:如何在不影响超类的情况下覆盖子类中的变量?
答案 0 :(得分:8)
类常量可以满足您的需求,您只需要以不同的方式使用它们:
class Foo
TEST = "a"
def speak
puts self.class::TEST
end
end
class Bar < Foo
TEST = "b"
end
Bar.new.speak # => a
Foo.new.speak # => b
答案 1 :(得分:4)
向类本身添加一个变量(如在类实例中,而不是类变量):
class Foo
@var = 'A'
class << self
attr_reader :var
end
def var
self.class.var
end
end
class Bar < Foo
@var = 'B'
end
Foo.var # A
Foo.new.var # A
Bar.var # B
Bar.new.var # B
答案 2 :(得分:2)
正确的方法(恕我直言)是使用方法,因为这样你就可以按照自己的意愿使用继承和虚拟调度。
类变量在层次结构中共享,而不是向上共享。这就是为@@bar
提供Object
的原因。