方法可见性可以在ruby中继承吗?

时间:2014-07-20 09:51:48

标签: ruby inheritance methods

请考虑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继承方法可见性?

2 个答案:

答案 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}}链中。