"超级"如何使用模块?

jan*_*o-m 5 ruby inheritance

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

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

ActionDispatch::Routing::Mapper.send(:include, DeleteResourceRoute)
Run Code Online (Sandbox Code Playgroud)

但是Ruby中的继承不是以模块是"超类"的方式工作的.那么他怎么能从#super模块中打电话呢?

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

class SomeClass
  alias old_method method
  def method
    # ...
    old_method
    # ...
  end
end
Run Code Online (Sandbox Code Playgroud)

可以这样做:

class SomeClass
  include Module.new {
    def method
      # ...
      super
      # ...
    end
  }
end
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

Siw*_*申思维 5

“超级”只存在于“阶级”环境中。super 不能生活在“纯模块”上下文中。所以,当你看到这样的代码时:

module DeleteResourceRoute
  def resources(*args, &block)
    super(*args) do
      # some code
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

你应该有一个类来“包含这个模块”,然后“超级”生效,例如

class SomeClass extends BaseClass
  include DeleteResourceRoute
end

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

SomeClass.new.resources  # => called parent!
Run Code Online (Sandbox Code Playgroud)


jan*_*o-m 4

我想到了。有一个模块包含在 中ActionDispatch::Routing::Mapper,并且该模块保存该#resources方法。如果#resources直接在 上定义ActionDispatch::Routing::Mapper,而不是在模块中定义,则以这种方式覆盖它是行不通的(我们必须使用“别名”方法来代替)。

一般来说,关于模块和类,模块的作用就像包含它的类的超类。我所说的“像超类一样”是指,如果您#foo在模块上定义了一个方法,并且将该模块包含到一个类中,则该类可以覆盖该#foo方法,并调用#super,这将调用该模块的#foo方法。一个例子:

module Foo
  def foo
    puts "foo"
  end
end

class Bar
  include Foo

  def foo
    super
    puts "bar"
  end
end

Bar.new.foo
# foo
# bar
# => nil
Run Code Online (Sandbox Code Playgroud)