“超级”如何使用模块?

时间:2012-10-14 22:22:42

标签: ruby inheritance

我将在一个具体的例子(在Rails中)问它。在“Destroy without Javascript (revised)”railscast中,Ryan Bates将覆盖#resources路由方法:

module DeleteResourceRoute
  def resources(*args, &block)
    super(*args) do
      # some code
    end
  end
end

ActionDispatch::Routing::Mapper.send(:include, DeleteResourceRoute)

但Ruby中的继承不是以模块是“超类”的方式工作的。他怎么能从模块中调用#super呢?

如果可以覆盖这样的方法,那么人们不会这样做:

class SomeClass
  alias old_method method
  def method
    # ...
    old_method
    # ...
  end
end

可能正在做这件事:

class SomeClass
  include Module.new {
    def method
      # ...
      super
      # ...
    end
  }
end

我错过了什么?

2 个答案:

答案 0 :(得分:4)

"超"只生活在" class"上下文。超级无法生活在一个纯粹的模块中。上下文。所以,当你看到如下代码时:

module DeleteResourceRoute
  def resources(*args, &block)
    super(*args) do
      # some code
    end
  end
end

你应该有一个班级来"包括这个模块",然后"超级"生效,例如

class SomeClass extends BaseClass
  include DeleteResourceRoute
end

class BaseClass
  def resources
    puts "called parent!"
  end
end

SomeClass.new.resources  # => called parent!

答案 1 :(得分:2)

我明白了。 ActionDispatch::Routing::Mapper中包含一个模块,该模块包含#resources方法。如果#resources直接在ActionDispatch::Routing::Mapper上定义,而不在模块中定义,则覆盖它将无法以这种方式工作(我们将不得不使用“别名”方法)。

关于模块和类,一般来说,模块就像包含它的类的超类一样。通过“表现得像一个超类”,我的意思是,如果你在模块上定义了一个方法#foo,并且你将该模块包含在一个类中,那么该类可以覆盖#foo方法,并调用{ {1}},这将调用模块的#super方法。一个例子:

#foo