Ruby只调用子方法

时间:2013-06-27 15:24:28

标签: ruby inheritance

当我在一个孩子上调用一个实例方法但是孩子还没有定义它时,我想引发异常。鉴于代码:

class Parent
  def foo
    'hihi'
  end
end

class Child < Parent
end

是否可以以引发此异常的其他方式调用Child.new.foo

我明白我可以

class Parent
  def foo
    unless self.class.instance_methods(false).include? :foo
      raise Exception.new("Child didn't define foo!")
    end
    'hihi'
  end
end

我想知道是否可以在没有这个的情况下执行此操作以及我实际执行Child.new.foo调用的位置。

谢谢!

2 个答案:

答案 0 :(得分:5)

您是否需要简单的Parent个实例成功回复foo

如果您尝试制作抽象方法,只需在Parent#foo中引发异常,并避免在任何子类“super中调用foo

class Parent
  def foo
    raise "abstract Parent#foo"
  end
end

class Child < Parent
  # this will raise an exception
end

class OtherChild < Parent
  # this won't raise an exception
  def foo
    'blah'
  end
end

另一方面,您可以像这样使用方法检查

class Parent
  def foo
    if self.class.instance_method(:foo).owner == Parent
      raise "abstract" unless self.instance_of? Parent
    end
    "fifi"
  end
end

class Child < Parent
  # this will raise an exception
end

class OtherChild < Parent
  # this won't raise an exception
  def foo
    'blah'
    super
  end
end

这具有定义该方法的任何中间类将阻止该异常的属性。

如果你想强制每个子类来定义方法(不仅仅是有一些中间定义),你可以使用

if self.class.instance_method(:foo).owner != self.class

作为条件

答案 1 :(得分:1)

这是一种方法:在基类中实现inherited(参见Ruby docs),并从那里定义要强制子类覆盖的方法:

class Parent
  def self.inherited(child)
    child.send(:define_method, :foo) do
      raise "You must implement #{child}#foo!"
    end
  end

  def foo
    'hihi'
  end
end

现在,任何继承自Parent的类都将以引发异常的foo方法开始。当您在派生类中显式实现foo时,它将覆盖此默认实现。

我喜欢这种方法,它不应该为每次foo的调用增加额外的开销。