程式扎記: [ Ruby Gossip ] Advance : 方法 - inherited、included、extended 方法

標籤

2014年12月9日 星期二

[ Ruby Gossip ] Advance : 方法 - inherited、included、extended 方法

Source From Here
Preface
透過 inherited、included、extended 方法, 你可以動態為物件或是類別加入特性或方法. 可以把這三個方法是為引入模組或是繼承類別時的 callback 函數!

inherited、included、extended 方法
如果類別定義有 inherited 類別方法,被子類別繼承時,inherited 會被呼叫,並傳入子類別作為引數。例如:


注意 inherited 被執行的時機,是在子類別本體執行之前。一個應用的例子,在 抽象類別與介面 中談過,模擬了 Java 中抽象類別的概念。

如果模組中定義有 included 模組方法,在被其它類別含括時,included 方法會被呼叫,並傳入含括類別的模組作為引數。例如:


一個應用的例子,在 抽象類別與介面 中談過,用模組來模擬 Java 中 interface 的概念。另一個常見應用,是讓模組可以定義各類別共用的類別方法。例如:
  1. module M1  
  2.     def self.included(clz)  
  3.         def clz.execute  
  4.             puts "共用的 execute 類別方法"  
  5.         end  
  6.     end  
  7. end  
  8.   
  9. class Some  
  10.     include M1  
  11. end  
  12.   
  13. class Other  
  14.     include M1  
  15. end  
  16.   
  17. Some.execute    # 顯示 "共用的 execute 類別方法"  
  18. Other.execute   # 顯示 "共用的 execute 類別方法"  
如果模組定義有 extended 方法,其它實例使用 extended 方法擴充模組時,extended 方法會被呼叫,並傳入實例作為引數。例如:


就類別而言,開啟類別使用 included 來含括模組,與使用實例的 extended 來擴充模組,雖然作用是相同的,但會觸發的方法並不同,分別是 included 與 extended,你也可以同時定義兩個方法,讓 include 與 extend 時,都呼叫同一個方法:
  1. # encoding: utf-8  
  2. module M1  
  3.     def self.included(clz)  
  4.         self.set_execute_class_method(clz)  
  5.     end  
  6.   
  7.     def self.extended(obj)  
  8.         self.set_execute_class_method(obj)  
  9.     end  
  10.   
  11.     def self.set_execute_class_method(unt)  
  12.         def unt.execute  
  13.             puts "#{self}: 共用的 execute 方法"  
  14.         end  
  15.     end  
  16. end  
  17.   
  18. class Some; end  
  19. class Other; end  
  20. class SomeOther  
  21.     include M1  
  22. end  
  23.   
  24. s = Some.new  
  25. s.extend(M1)  
  26. s.execute           # 顯示 "??? 共用的 execute 方法"  
  27.   
  28. Some.extend(M1)  
  29. Other.extend(M1)  
  30.   
  31. Some.execute        # 顯示 "??? 共用的 execute 方法"  
  32. Other.execute       # 顯示 "??? 共用的 execute 方法"  
  33. SomeOther.execute   # 顯示 "??? 共用的 execute 方法"  


沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!