52

在 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>'
4

3 回答 3

79

我通过简单地重新定义子类中的常量,然后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!"
于 2012-11-05T14:50:00.160 回答
8

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

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

对于 self 方法: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!"
于 2018-06-18T17:36:24.010 回答
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!
于 2020-01-08T16:19:17.720 回答