Ruby从Superclass方法产生子类方法

时间:2015-02-04 22:40:16

标签: ruby inheritance metaprogramming

在Ruby中,是否可以从超类方法中获取子类方法而不影响子类中的代码?我试图避免在子类中调用super

class SuperClass
  def do_something
    puts "getting ready..."
    # how to then yield back to the subclass do_something method?
    puts "done."
  end
end

class SubClass < SuperClass
  def do_something
    # how to first execute the superclass do_something method?
    puts "doing something ..."
  end
end

所需功能是专门致电SubClass.do_something并收到以下输出:

“准备好......”

“做某事......”

“来完成。”


编辑:

也许真正的问题是:如何干掉下面的代码,从所有子类中删除对self.get_readyself.finish_up的调用,使用任何保留这些类的ruby元编程技术DRY:< / p>

class SuperClass
  def self.get_ready
    puts "getting ready ..."
  end

  def self.finish_up
    puts "done."
  end
end

class SubClassA < SuperClass
  def self.do_something
    self.get_ready
    puts "doing something ..."
    self.finish_up
  end
end

class SubClassB < SuperClass
  def self.do_something
    self.get_ready
    puts "doing something else, a little differently..."
    self.finish_up
  end
end

class SubClassC < SuperClass
  def self.do_something
    self.get_ready
    puts "doing something crazy..."
    self.finish_up
  end
end

2 个答案:

答案 0 :(得分:4)

如果你真的不愿意使用super,这几乎是不可能的。

使用super,非常简单:

class SuperClass
  def do_something
    puts "getting ready..."
    yield
    puts "done."
  end
end

class SubClass < SuperClass
  def do_something
    super.do_something do
      puts "doing something..."
    end
  end
end

另一方面,如果您对多种方法持开放态度,则不使用super,这会变得更简单:

class SuperClass
  def do_something
    puts "getting ready..."
    self.actually_do_the_thing
    puts "done."
  end
  def actually_do_the_thing
    raise NotImplementedError
  end
end

class SubClass < SuperClass
  def actually_do_the_thing
    puts "doing something..."
  end
end

答案 1 :(得分:4)

Practical Object-Oriented Design in Ruby中,Sandi Metz建议您克服呼叫超级的方法是定义一个&#34; hook&#34;超类中的方法,只有作业才会被子方法覆盖。在你的情况下,你可以做这样的事情:

class SuperClass
  def self.do_something
    puts "getting ready..."
    do_something_child
    puts "done."
  end

  def self.do_something_child; end
end

class SubClass < SuperClass
  def self.do_something_child
    puts "doing something ..."
  end
end

SubClass.do_something