【问题标题】:Ruby Yield to Subclass Method from Superclass MethodRuby 从超类方法生成子类方法
【发布时间】:2015-04-04 15:46:11
【问题描述】:

在 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​​ 元编程技术:

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

【问题讨论】:

  • 既然你有单例方法,继承是无关紧要的。
  • 您正在尝试的是设计缺陷。 SubClass#do_something 致电 SubClass#do_something。您可以在其中调用SuperClass#do_something,但不能反过来。

标签: ruby inheritance metaprogramming


【解决方案1】:

如果你真的不愿意使用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

【讨论】:

  • 是的,目标是避免在子类中使用任何代码(包括super)。
  • 如果您希望子类中没有代码,那么您首先如何期望在行为上有任何有意义的差异?
  • 请注意,OP 改变了问题。
【解决方案2】:

Practical Object-Oriented Design in Ruby 中,Sandi Metz 建议您克服调用 super 的方法是在超类中定义一个“挂钩”方法,该方法唯一的工作就是被子方法覆盖。在你的情况下,你可以这样做:

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

【讨论】:

    猜你喜欢
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    相关资源
    最近更新 更多