防止Ruby中的继承

时间:2014-04-28 15:00:11

标签: ruby inheritance

我试图找出如何防止所有子类中的一个方法的继承。目前我正在尝试使用这样的代码:

class Mother

  def phone
    puts "#{self.class} phoned"
  end

  protected
  def phone_kids
    puts "phoned kids"
  end
end

class Kid < Mother
end

但是没有任何结果,因为我收到了这样的错误:<top (required)>': protected method 'phone_kids' called for #<Mother:0x604da0> (NoMethodError)。能否简要解释一下Ruby中的继承是如何工作的?

提前致谢!

//编辑:

我使用此代码收到此错误:

kid = Kid.new
mom = Mother.new

mom.phone_kids

3 个答案:

答案 0 :(得分:10)

如果您发现自己需要这样做,则可能意味着您没有正确使用继承。如果 C 类继承自 D ,那么它应该是一个“是一个”关系:每个 C 都是 D 。既然不是每个孩子都是母亲,那么在这种情况下使用遗产是不好的。

以下是如何使用单个类代表Ruby中的父母和孩子:

class Person
  attr_accessor :name
  attr_accessor :children

  def initialize(name)
    @name = name
    @children = []
  end

  def phone_kids
    @children.each { |c| c.phone }
  end

  def phone
    puts "#{@name} phoned"
  end
end

现在,回答原来的问题。如果您想阻止Kid类继承phone_kids方法,您可以执行以下操作:

class Mother

  def self.inherited(klass)
    klass.send(:define_method, :phone_kids) do
      raise NoMethodError
    end
  end 

  def phone_kids
    puts "phoned kids"
  end
end

class Kid < Mother
end

Mother.new.phone_kids  # => phoned kids
Kid.new.phone_kids     # => NoMethodError

答案 1 :(得分:1)

在ruby中,private和protected方法都只能在def类中使用。因此,您无法在外部调用受保护或私有方法:

class Mother

  def phone
    puts "#{self.class} phoned"
  end

  protected
  def phone_kids
    puts "phoned kids"
  end
  private
  def anoter_phnoe_kids
    puts "anoter phoned kids"
  end
end

class Kid < Mother
  def hey
    phone_kids
    anoter_phnoe_kids
  end
end

Kid.new.phone #OK
Kid.new.phone_kids #protected method (NoMethodError)
Kid.new.anoter_phnoe_kids #private method (NoMethodError)
Kid.new.hey #OK

here显示protectedprivate之间的差异。

答案 2 :(得分:1)

  

受保护和私密之间的区别是微妙的。如果方法受到保护,则可以由定义类或其子类的任何实例调用它。如果一个方法是私有的,那么它只能在调用对象的上下文中调用---它永远不可能直接访问另一个对象实例的私有方法,即使该对象与调用者属于同一个类。对于受保护的方法,可以从同一类(或子类)的对象访问它们.`

来源:http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes#Declaring_Visibility