如何在 ruby​​ 中使基类方法不可重写?

发布于 2024-07-16 01:56:38 字数 707 浏览 7 评论 0原文

我有一些基类 A ,其方法不可被重写。

class A
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end

另一个类 B 扩展了 A 并尝试重写 dont_override_me 方法。

class B < A
  def dont_override_me
    puts 'class B saying, "This is my implementation!"'        
  end
end

如果我实例化 B 并调用 dont_override_me,则将调用类 B 的实例方法。

b = B.new
b.dont_override_me # => class B saying, "This is my implementation!"

这是因为红宝石的特性。 可以理解。

但是,如何强制基类方法 dont_override_me 不可被其派生类覆盖? 我在 ruby​​ 的 java 中找不到像 final 这样的关键字。 在 C++ 中,可以将基类方法设为非虚拟方法,以便派生类无法重写它们。 我如何在红宝石中实现这一目标?

I have some base class A with a method that is not to be overridden.

class A
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end

And another class B that extends A and tries to override the dont_override_me method.

class B < A
  def dont_override_me
    puts 'class B saying, "This is my implementation!"'        
  end
end

If I instantiate B and call dont_override_me, class B's instance method will be called.

b = B.new
b.dont_override_me # => class B saying, "This is my implementation!"

This is because of ruby's properties. Understandable.

However, how do I force the base class method dont_override_me to be non-overridable by it's derived classes? I could not find a keyword like final in java for ruby. In C++, the base class methods can be made non-virtual so that they become non-overridable by the derived classes. How do I achieve this in ruby?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一曲爱恨情仇 2024-07-23 01:56:38

您可以通过挂钩更改事件并将其改回来来做到这一点,但对我来说似乎有点难闻:

http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby

这是定义 Ruby 的东西之一,所以在我看来,反对它似乎有点毫无意义。 如果有人重新定义了某些东西,导致它严重损坏..那就是他们的问题;-)

You can do it, by hooking the change event and changing it back, but it seems a bit smelly to me:

http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby

It's one of those things that sort of defines Ruby, so fighting against it seems a little pointless imo. If someone redefines something so it breaks horribly.. that's their problem ;-)

等往事风中吹 2024-07-23 01:56:38

这是一种方法:
http://www.thesorensens .org/2006/10/06/final-methods-in-ruby-prevent-method-override/

这也被打包到一个名为“finalizer”的 gem 中(gem install Finalizer),

这利用了 method_linked回调并将新方法名称与您希望成为 final 的方法列表进行比较。

Here's a way to do it:
http://www.thesorensens.org/2006/10/06/final-methods-in-ruby-prevent-method-override/

This has also been packaged into a gem called "finalizer" (gem install finalizer)

This makes use of the method_added callback and compares the new method name with a list of methods that you wish to make final.

旧竹 2024-07-23 01:56:38

我建议:

class A #This is just as you've already defined it.
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end

module BehaviorForB
  def dont_override_me
    puts 'class B saying, "This is my implementation!"'        
  end

  def greet
    "Hello, Friend."
  end
end

class B < A
  include BehaviorForB
end

b = B.new
b.dont_override_me #=> class A saying, "Thank you for not overriding me!"
b.greet #=> Hello, Friend.

通过将 B 的方法隐藏在 mixin 中,您将得到您想要的。 A 中尚未存在的 B 方法中的任何方法都将可用。 A 中已有的方法不会被覆盖。

I recommend:

class A #This is just as you've already defined it.
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end

module BehaviorForB
  def dont_override_me
    puts 'class B saying, "This is my implementation!"'        
  end

  def greet
    "Hello, Friend."
  end
end

class B < A
  include BehaviorForB
end

b = B.new
b.dont_override_me #=> class A saying, "Thank you for not overriding me!"
b.greet #=> Hello, Friend.

By keeping B's methods tucked away in an mixin, you get exactly what you desire. Any method of B's methods that are not already in A will be available. Methods that are already in A will not be overridden.

枕头说它不想醒 2024-07-23 01:56:38

防止方法被子类覆盖的一种方法(但不推荐):

class Class
  def frozen_method(method)
    if class_variable_defined?(:@@__frozen_methods__)
      add= class_variable_get(:@@__frozen_methods__) | [method]
      class_variable_set(:@@__frozen_methods__,add)
    else
      class_variable_set(:@@__frozen_methods__,[method])
    end
    class << self
      def inherited(child)
        def method_added(method)
          if class_variable_get(:@@__frozen_methods__).include? method
            send(:remove_method, method)
            error="Cannot change method #{method} because it's not overridde"
            raise TypeError, error
          end
        end
      end
    end
  end
end

class Foo
  def hello
    'hello'
  end
  def foo
    'foo'
  end

  frozen_method :foo
end

class Bar < Foo
  def foo
    'new foo'
  end
end

#=> TypeError: Cannot change method foo because it's not overridde

Bar.new.foo  #=> 'foo'

警告:此示例不完整。 如果您为子类中先前定义的方法添加frozen_method,则当该方法在子类中被修改时,它将丢失其实现。

One way to prevent a method from being overridden by a subclass (but not recommend) :

class Class
  def frozen_method(method)
    if class_variable_defined?(:@@__frozen_methods__)
      add= class_variable_get(:@@__frozen_methods__) | [method]
      class_variable_set(:@@__frozen_methods__,add)
    else
      class_variable_set(:@@__frozen_methods__,[method])
    end
    class << self
      def inherited(child)
        def method_added(method)
          if class_variable_get(:@@__frozen_methods__).include? method
            send(:remove_method, method)
            error="Cannot change method #{method} because it's not overridde"
            raise TypeError, error
          end
        end
      end
    end
  end
end

class Foo
  def hello
    'hello'
  end
  def foo
    'foo'
  end

  frozen_method :foo
end

class Bar < Foo
  def foo
    'new foo'
  end
end

#=> TypeError: Cannot change method foo because it's not overridde

Bar.new.foo  #=> 'foo'

Warning: this example is not complete. If you add frozen_method for a previously defined method in the subclass, when this method will be modified in the subclass, it will lose its implementation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文