我将在一个具体的例子(在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)
我错过了什么?
“超级”只存在于“阶级”环境中。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)
我想到了。有一个模块包含在 中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)