在ruby中,當某些特定的事件發生時,將調用回調方法和鉤子方法。事件有如下幾種:
- 調用一個不存在的對象方法
- 類混含一個模塊
- 定義類的子類
- 給類添加一個實例方法
- 給對象添加一個單例方法
- 引用一個不存在的常量
對以上的事件,都可以為之編寫一個回調方法,當該事件發生時,這個回調方法被執行。這些回調方法是針對某個對象,或者某個類的,而不是全局的。
?
下面給出一些例子:
1?Method_missing攔截不能識別的消息
在前面說過,根據對象模型來進行方法查找,如果沒有找到,會拋出一個NoMethodError異常,除非定義了一個名為method_missing的方法。
如下:
1 class C 2 def method_missing(m) 3 puts "there is no method #{m}" 4 end 5 end 6 C.new.hello
輸出:
there is no method hello
類C中沒有定義實例方法hello(它的方法查找路徑上也沒有),因此調用method_missing。
?
2?用Module#included捕捉混含操作
當一個模塊被混入到類(或者另一個模塊)中,如果該模塊的included方法已經定義,那么該方法就會被調用。該方法的參數就是混入該模塊的類。
如下:
1 module M 2 def self.included(c) 3 puts "module M is included by #{c}" 4 end 5 end 6 class C 7 include M 8 end
輸出:
module M is included by C
當模塊M被混入到C中,模塊M的included方法被調用了。
這種方式可以用來定義類方法,如上面的代碼中,在self.included中就可以定義類c的類方法,或者給單例類添加一個模塊
如下:
1 module M 2 def self.included(c) 3 puts "module M is included by #{c}" 4 5 def c.m1 6 puts "this is class #{c}'s class method m1 " 7 end 8 9 c.extend(N) 10 end 11 module N 12 def method 13 puts "hello world" 14 end 15 end 16 end 17 class C 18 include M 19 end 20 p C.singleton_methods
輸出:
module M is included by C
[:m1, :method]
如代碼,5-7行定義了一個類方法,該類是包含模塊M的類(此例中就是C),9行將模塊N加入了該類的單例類中。在20行的輸出類C的單例方法可以看出加入成功。
?
3 用Class#inherited攔截繼承
當為一個類定義了inherited方法,那么在為它生成子類時,inherited會被調用,唯一的調用參數就是新的子類的名字。
如下:
1 class C 2 def self.inherited(subclass) 3 puts "#{self} got a new subclass #{subclass} " 4 end 5 end 6 class D < C 7 end 8 class E < D 9 end
輸出:
C got a new subclass D
D got a new subclass E
當D繼承C時,調用了這個鉤子方法,輸出C got a new subclass D。同時,D的單例類中也有了C的類方法,因此在E繼承D時,也會調用調用D的這個鉤子方法。
?
4 Module#const_missing
當給定的模塊或者類中引用了一個不可識別的常量時,該方法被調用。
如下:
1 class C 2 def self.const_missing(const) 3 puts "#{const} is undefined-setting " 4 const_set(const,1) 5 end 6 end 7 puts C::A
輸出
A is undefined-setting
1
常量A沒有被定義,因此調用了const_missing方法。在方法中把它定義為1。
?
5 Module#method_added
當新定義一個方法時,會調用這個方法。
如下:
1 module M 2 def self.method_added(method) 3 puts "method #{method} is added in M" 4 end 5 def m1 6 end 7 end
輸出
method m1 is added in M
?
ruby中鉤子方法很多,覆蓋了絕大多數值得注意的事件。這里只給出一些常見的,給自己參考,給大家參考。
?