我有一些基类A,其方法不能被覆盖。
class A
def dont_override_me
puts 'class A saying, "Thank you for not overriding me!"'
end
end
另一个扩展A并尝试覆盖dont_override_me
方法的B类。
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!"
这是因为ruby的属性。可以理解的。
但是,如何强制基类方法dont_override_me
不能被它的派生类覆盖?我在java的ruby中找不到像final
这样的关键字。在C ++中,基类方法可以是非虚拟的,这样它们就不会被派生类覆盖。我如何在ruby中实现这一目标?
答案 0 :(得分:6)
您可以通过挂钩更改事件并将其更改回来来实现,但对我来说似乎有点臭:
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
这是定义Ruby的那些东西之一,所以与它的斗争似乎有点无意义的imo。如果有人重新定义了某些东西,那么它就会破碎......这就是他们的问题; - )
答案 1 :(得分:4)
这是一种方法: http://www.thesorensens.org/2006/10/06/final-methods-in-ruby-prevent-method-override/
这也被打包成一个叫做“终结者”(gem install finalizer)的宝石
这会使用method_added回调,并将新方法名称与您希望制作final
的方法列表进行比较。
答案 2 :(得分:1)
我建议:
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的方法隐藏在混合物中,你可以得到你想要的东西。 B的方法的任何方法都不在A中。已经在A中的方法将不会被覆盖。
答案 3 :(得分:0)
防止方法被子类覆盖的一种方法(但不推荐):
response = b'''{"products": [
{
"upc": "715187763623",
"sku": 1833591,
"salePrice": 13.99
},
{
"upc": "8809269504036",
"sku": 26220187,
"salePrice": 16.99
}
]
}'''
json_obj = json.loads(response.decode('utf-8'))
#print(json_obj["products"][0]["upc"])
for product in json_obj["products"]:
print("upc:", product["upc"])
print("sku:", product["sku"])
print("salePrice:", product["salePrice"])
print('---')
cursor.execute("INSERT INTO bestb (sku, upc, salePrice) VALUES (%s,%s,%s)", (product["sku"], product["upc"], product["salePrice"]))
警告:此示例未完成。如果在子类中为先前定义的方法添加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'
,则在子类中修改此方法时,它将失去其实现。