请考虑Ruby
中的以下示例:
class ParentClass
private def method
puts "private method"
end
end
class ChildClass < ParentClass
def method
puts "overridden, but should be private too"
end
end
ParentClass.new.method #=> raises exception
ChildClass.new.method #=> produces "overridden, but should be private too"
如果我无法控制ChildClass
的代码,是否可以从ParentClass
继承方法可见性?
答案 0 :(得分:4)
你的问题与继承无关。这里的相关内容是类方法private
的时间安排。请参阅下面的简化示例。调用时,此方法将此时存在的relavant方法转换为私有方法。
class A
def foo; "foo1" end
private :foo
new.foo # => NoMethodError: private method `foo' called for #<A:0x007f321204fec0>
end
在应用private
之后更改方法时,会定义一个具有相同名称的新方法,并且应用于先前定义的private
的效果消失。
class A
def foo; "foo2" end
new.foo # => "foo2"
end
当您再次呼叫private
时,它就会变为私密状态:
class A
private :foo
new.foo # => NoMethodError: private method `foo' called for #<A:0x007f3211ff6de8>
end
使用原始示例来说明这一点......
class ChildClass
private :method
end
...可以在ChildClass的初始定义之后完成,并将method
方法设为私有。
总而言之,可见性是(已定义)方法的属性,而不是方法名称的属性。因此,您无法重新定义方法,但具有相同名称的先前方法的私有状态,但您可以更改当前方法的私有状态。
答案 1 :(得分:1)
所有对象首先更喜欢他们的自己的定义的方法,即使他们的父类也有相同的命名方法。但是如果您真的想要在某些情况下调用父类方法,那么您可以从#class_eval
获取相同的帮助:
class ParentClass
private
def biz
puts "private method"
end
end
class ChildClass < ParentClass
def biz
puts "overridden, but should be private too"
end
end
ChildClass.class_eval do
remove_method :biz
self.new.biz
end
# private method `biz' called for #<ChildClass:0x8c3532c> (NoMethodError)
现在,请参阅ChildClass
对象正在调用ParentClass
中的私有方法。现在要使呼叫成功,您需要使用#send
。
ChildClass.class_eval do
remove_method :biz
self.new.send :biz # => private method
end
另一种方式,我在大多数情况下使用的是: -
unbind = ParentClass.instance_method(:biz)
unbind.bind(ChildClass.new).call # => private method
实际上,当你继承或 mixin 时,无论什么方法都没有在物理上不分别进入孩子或混合在一起。它们(父类或混合模块)实际上已添加到类ChildClass
的{{3}}链中。