你有多少種方式建立一個方法?大多數人想到的可能是def 關鍵字 Ruby代碼
- #普通方法
- def tele_you
- puts "I am Anleb"
- end
#普通方法def tele_you puts "I am Anleb"end
Ruby代碼
- #定義單件方法
- n="Anleb"
- def n.tell_you
- puts "I am #{self}"
- end
- n.tell_you
#定義單件方法n="Anleb"def n.tell_you puts "I am #{self}"endn.tell_you
Ruby代碼
- #define_method
- class Project
- define_method :tell_you do |name|
- puts name
- end
- end
-
- a=Project.new
- a.tell_you("Anleb")
#define_methodclass Project define_method :tell_you do |name| puts name endenda=Project.newa.tell_you("Anleb")
具體分析下:define_method方法 Ruby代碼
- Kernel.private_methods.include?("define_method") #true
Kernel.private_methods.include?("define_method") #true
可以看到define_method是一個私人方法,那麼私人方法調用是有規定的:
1.不能有顯式調用,也就是不能有接受者,不能self.define_method這樣調用
2.私人方法是可以被繼承的
3.私人方法可以被send強制調用,如:send(:private_method)
4.只能在自身中調用私人方法(體會下這句話的意思)
上面Project類中,當前self是類Project,然後隱式調用define_method方法建立方法
define_methods動態建立方法,什麼是動態建立呢,就是代碼運行時就建立定義了方法,利用動態建立和動態派發可以實現ruby的代碼重構,這是魔法!
例子元編程書上有,中文版 46頁,英文版69頁
看一個例子:
- class Project1
- define_method :tell_you do |name|
- puts name
- end
- end
-
- class Project2 < Project1
-
- end
-
- a=Project2.new
- a.tell_you("Anleb")
- Project1.instance_methods(false) #["tell_you"]
class Project1 define_method :tell_you do |name| puts name endendclass Project2 < Project1 enda=Project2.newa.tell_you("Anleb")Project1.instance_methods(false) #["tell_you"]
1.說明define_method定義的方法和def定義沒區別,都可以被繼承
2.define_method的方法是存在於類中的執行個體方法
修改代碼: Ruby代碼
- class Project1
- define_method :tell_you do |name|
- puts name
- end
-
- def creat_method
- define_method :new_method do
- puts "this is a new method"
- end
- end
- end
- Project1.new.creat_method
-
-
- Error:test.rb:7:in `creat_method': undefined method `define_method' for #<Project1:0x2bc7008> (NoMethodError)
class Project1 define_method :tell_you do |name| puts name end def creat_method define_method :new_method do puts "this is a new method" end endendProject1.new.creat_methodError:test.rb:7:in `creat_method': undefined method `define_method' for #<Project1:0x2bc7008> (NoMethodError)
一拍腦袋,額,忘記說了,define_method是Object Class方法,也就是只有類才可以調用,
creat_method的當前self肯定是一個對象啊,對象不是類,所以不能調用,修改代碼
- def creat_method
- self.class.define_method :new_method do
- puts "this is a new method"
- end
- end
def creat_method self.class.define_method :new_method do puts "this is a new method" end end
調用方法:
- Project1.new.creat_method
- Error:test.rb:7:in `creat_method': private method `define_method' called for Project1:Class (NoMethodError)
Project1.new.creat_methodError:test.rb:7:in `creat_method': private method `define_method' called for Project1:Class (NoMethodError)
崩潰了,怎麼還不行,看看提示,說這是一個私人方法,額。。。忘記了,private方法不能顯式有接受者,我們想到一個辦法,對,那就是send方法
修改代碼:
- class Project1
- define_method :tell_you do |name|
- puts name
- end
-
- def creat_method
- self.class.send(:define_method,:new_method) do
- puts "this is a new method"
- end
- end
- end
-
- a=Project1.new
- p Project1.instance_methods(false) #["creat_method", "tell_you"]
- a.creat_method
- p Project1.instance_methods(false) #["creat_method", "tell_you"]
class Project1 define_method :tell_you do |name| puts name end def creat_method self.class.send(:define_method,:new_method) do puts "this is a new method" end endenda=Project1.newp Project1.instance_methods(false) #["creat_method", "tell_you"]a.creat_methodp Project1.instance_methods(false) #["creat_method", "tell_you"]
終於成功了,這種技術叫做 動態派發技術,常用在Method_messing方法。
解法2: Java代碼
- class Project1
- define_method :tell_you do |name|
- puts name
- end
-
- def self.creat_method
- define_method :new_method do #當前self是類,所以可以調用,並且隱式
- puts "this is a new method"
- end
- end
- creat_method
- end
-
- Project1.new.new_method
class Project1 define_method :tell_you do |name| puts name end def self.creat_method define_method :new_method do #當前self是類,所以可以調用,並且隱式 puts "this is a new method" end end creat_methodendProject1.new.new_method
解法3: Ruby代碼
- class Project1
- class << self
- def creat_method
- define_method :new_method do #當前self是類
- puts "this is a new method"
- end
- end
- end
- creat_method
- end
-
- Project1.new.new_method
class Project1 class << self def creat_method define_method :new_method do #當前self是類 puts "this is a new method" end end end creat_methodendProject1.new.new_method
研究的不好,有錯誤大家交流!