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

Aje*_*i32 40 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!"
Run Code Online (Sandbox Code Playgroud)

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

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!"
Run Code Online (Sandbox Code Playgroud)

注意:我在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>'
Run Code Online (Sandbox Code Playgroud)

Zac*_*emp 63

我通过简单地重新定义子类中的常量,然后在方法中引用它来实现这一点,如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!"
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是一种很好的方式.不幸的是,它不适用于我的情况,因为我想要覆盖常量的类是外部库(宝石)的一部分,我真的不想搞砸. (3认同)
  • @Jazz不太好.我希望宝石的行为与现在完全一样.它是我想要改变它的行为的子类,而不是超类,我想这样做而不必在我的代码库中复制一大块gem的代码.(例如,如果gem在其20个方法中引用了`CONST`,我不想覆盖所有这20个方法,复制它们的所有代码,只是因此我可以将它们更改为引用`self :: CONST`代替.) (2认同)

Bha*_*caz 6

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

对于实例方法: 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!"
Run Code Online (Sandbox Code Playgroud)