2012-10-14 34 views
4

我會問一個具體的例子(在Rails中)。在「Destroy without Javascript (revised)」 railscast,瑞恩·貝茨將覆蓋#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

順便說一下:這正是Ruby 2.0中的'prepend'。 –

回答

1

我想通了。有一個模塊包含在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 
4

「super」僅存在於「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! 
+0

'Module' * does *有一個方法':: new',這就是你動態創建新模塊的方法。 –

相關問題