Ruby从超类方法转换为子类方法

s2t*_*2t2 1 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
Run Code Online (Sandbox Code Playgroud)

所需的功能是专门调用SubClass.do_something并接收以下输出:

“准备...”

“做某事...”

“做完了。”


编辑:

也许真正的问题是:如何干涸下面的代码,删除对来电self.get_readyself.finish_up所有子类,使用任何红宝石的元编程技术,保持这些类DRY:

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
Run Code Online (Sandbox Code Playgroud)

Pla*_*ure 6

如果您真的不愿意使用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
Run Code Online (Sandbox Code Playgroud)

另一方面,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
Run Code Online (Sandbox Code Playgroud)

  • 如果您不想在子类中使用任何代码,那么您首先希望在行为上有什么有意义的差异? (2认同)

dar*_*mkd 5

Ruby中的实用面向对象设计中,Sandi Metz建议您克服超级调用的方法是在超类中定义“钩子”方法,唯一的工作就是被子方法覆盖。在您的情况下,您可以执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)