在Ruby中,有没有办法在子类中“覆盖”常量,以便继承的方法使用新常量而不是旧常量?

时间:2012-11-05 14:43:04

标签: ruby

在Ruby中,有没有办法在子类中“覆盖”一个常量,这样从子类调用一个继承的方法会导致该方法使用新的常量而不是旧的常量?例如:

class SuperClass
  CONST = "Hello, world!"
  def self.say_hello
    CONST
  end
end

class SubClass < SuperClass
  override_const :CONST, "Hello, Bob!"
end

SuperClass.say_hello # => "Hello, world!"
SubClass.say_hello   # => "Hello, Bob!"

如果没有,是否有办法做这样的事情呢?

class SuperClass
  CONST = "Hello, world!"
  def self.say_hello
    CONST
  end
end

SubClass = SuperClass.clone
SubClass.send(:remove_const, :CONST)
SubClass.const_set(:CONST, "Hello, Bob!")

SubClass.say_hello # => "Hello, Bob!"

注意:我在irb中尝试了我的第二个例子,它似乎有效,除了在克隆类之后类方法似乎无法访问CONST:

irb(main):012:0> SubClass.say_hello
NameError: uninitialized constant Class::CONST
        from (irb):4:in `say_hello'
        from (irb):12
        from C:/Ruby193/bin/irb:12:in `<main>'

3 个答案:

答案 0 :(得分:58)

我通过简单地重新定义子类中的常量,然后在方法中将其引用为实例方法中的self.class::CONST和类方法中的self::CONST来完成此操作。在您的示例中:

class SuperClass
  CONST = "Hello, world!"
  def self.say_hello
    self::CONST
  end
end

class SubClass < SuperClass
  CONST = "Hello, Bob!"
end

SubClass.say_hello #=> "Hello, Bob!"

答案 1 :(得分:2)

你可以在父类中引用这样的常量:

对于实例方法:self.class::CONST

对于自我方法:self::CONST

class SuperClass
  CONST = "Hello, world!"
  def print_const
    puts self.class::CONST
  end

  def self.print_const
    puts self::CONST
  end

end

class SubClass < SuperClass
  CONST = "Hello, Bob!"
end

SubClass.new.print_const #=> "Hello, Bob!"
SubClass.print_const #=> "Hello, Bob!"

答案 2 :(得分:2)

如果您有能力更改基类,请考虑在基类中包装需要在类方法中进行更改的“常量”,并根据需要在子类中覆盖它们。这消除了父常量和子类常量之间混淆的可能性。对于此示例,如下所示:

class SuperClass
  CONST = "Hello, world!".freeze

  def self.const
    CONST
  end

  def self.say_hello
    const
  end
end

class SubClass < SuperClass
  CONST = "Hello, Bob!".freeze

  def self.const
    CONST
  end
end

SubClass.say_hello #=> "Hello, Bob!