Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使基类方法在ruby中不可重写?_Ruby_Oop_Overriding - Fatal编程技术网

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

如何使基类方法在ruby中不可重写?,ruby,oop,overriding,Ruby,Oop,Overriding,我有一个基类A,它有一个不被重写的方法 class A def dont_override_me puts 'class A saying, "Thank you for not overriding me!"' end end 另一个类B扩展了A并试图覆盖don\u override\u me方法 class B < A def dont_override_me puts 'class B saying, "This is my implementation

我有一个基类A,它有一个不被重写的方法

class A
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end
另一个类B扩展了A并试图覆盖
don\u override\u me
方法

class B < A
  def dont_override_me
    puts 'class B saying, "This is my implementation!"'        
  end
end
这是因为ruby的属性。可以理解


但是,如何强制基类方法
dont\u override\u me
不被其派生类重写?我在java for ruby中找不到像
final
这样的关键字。在C++中,基类方法可以非虚拟化,以便它们由派生类变得不可重写。我如何在ruby中实现这一点?

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

它是定义Ruby的东西之一,所以在我看来,反对它似乎有点毫无意义。如果有人重新定义了某个东西,那么它会崩溃得很厉害。。这就是他们的问题;-)

这里有一个方法:

这也被打包到一个名为“finalizer”(gem安装finalizer)的gem中

这将使用添加的回调方法,并将新方法名称与希望生成的方法列表进行比较。
final

我建议:

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.
class A#这就像您已经定义的那样。
不要凌驾于我之上
把“A级说“谢谢你没有压倒我!”
结束
结束
模块行为FORB
不要凌驾于我之上
把“B类说,“这是我的实现!”
结束
def问候
“你好,朋友。”
结束
结束
B类你好,朋友。

把B的方法藏在混合器里,你就能得到你想要的。B的方法中尚未包含在A中的任何方法都将可用。不会重写已在中的方法。

防止子类重写方法的一种方法(但不推荐):

class A
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end
类
def冻结法(方法)
如果定义了类变量(:@@@冻结的方法)
add=class_variable_get(:@@uu冻结的方法)|[method]
类变量集(:@@@冻结的方法,添加)
其他的
类变量集(:@@@冻结的方法,[方法])
结束
类TypeError:无法更改方法foo,因为它未被重写
Bar.new.foo#=>“foo”

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

太好了,我想知道为什么这不是标准ruby API的一部分!我的意思是,这种情况非常普遍,但在设计语言时却没有处理……能够完全覆盖所有内容是Ruby的核心原则之一,所以“处理”有点违背它。你知道,如果纯粹主义者把这个放进Ruby的核心,他们会抱怨多少:-):)同意。但是,如果每次我们想这样做或使用gem时都必须向对象类添加一些代码,那也很痛苦。我在想,如果finalize方法(如下Gdeglin所示)是一个标准的RubyAPI,那就太好了。在rubyRemember中构建框架时,这种场景必须是常见的,但这仍然不能完全保护您。任何想要的人都可以在需要您的库之前要求“immutable”,并将immutable_方法重新定义为public的别名。Ruby是开放的。基本上是开放的。然后我们需要使immutable方法不可变:)您已经得到了答案,但我强烈建议您重新考虑一下想要这样做的原因:这在某些语言中是一种常见的习惯用法,比如Java,但在Ruby中它不是正常的行为,这可能会给你带来不必要的痛苦和困难。谢谢你的提醒!:)这并不是一个实际项目的要求。这个问题就这样冒出来了。但我想,在构建框架时,可能需要限制派生类重写方法。我在那里没有太多经验,但这是我的猜测。@Chirantan-你的问题和答案很有趣。我很高兴你问这个问题!但是,如果我发现一个gem或框架正在积极阻止我重写一个方法,这将是一个严重的WTF,我将停止使用该gem。实际上,当我运行代码时,
b.dont\u override\u me
return
“这是我的实现!”
。我想知道这是否是因为答案是旧的,可能使用了旧版本的Ruby。我在1.9.3上进行了测试
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'