8

假设我有一个带有一些“静态”变量的类。我希望该类的子类能够覆盖这些变量而不影响原始类。使用类变量是不可能的,因为这些变量似乎在子类和超类之间共享:

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设置?ObjectBar < Foo


总结一下:如何在不影响超类的情况下覆盖子类中的变量?

4

3 回答 3

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
于 2013-10-15T13:37:07.813 回答
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
于 2013-10-15T13:42:20.820 回答
3

正确的方法(恕我直言)是使用方法,因为这样你就可以使用继承和虚拟调度,就像你想要的那样。

类变量在层次结构中向下共享,而不是向上共享。这就是为什么@@barObject.

于 2013-10-15T13:36:37.027 回答