如何使基类方法在ruby中不可重写?
我有一个基类A,它有一个不被重写的方法如何使基类方法在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
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'