Source From Here
Preface
Ruby 中,方法本身並不直接以物件方式存在,然而可以透過 method 方法取得 Method 實例。例如:
取得 Method
可以看到,取得的 Method 實例,self 綁定的物件是 s,可以取得 Method 實例的應用之一,就是當你的物件公開介面不一致,但又想以統一方式取得呼叫結果時。例如:
Some 的 doSome 方法與 Other 的 doOther 方法,都是接受一個引數並傳回運算值,雖然方法介面不同,但 utility 方法仍可以進行呼叫運算。以 method 方法取得的 Method 實例,self 預設有綁定物件,可以使用 unbind 方法解除 self 的綁定(會取得 UnboundMethod 實例),使用 bind 方法再度綁定 self 的物件。例如:
method 可以取得實例上可呼叫的方法,包括單例方法,如果你想直接取得未綁定 self 的實例方法,也可以使用每個類別都有的 instance_method 方法(這個方法無法取得單例方法)。例如:
bind 可以綁定的對象,必須是同一類別或子類別實例(但無法綁定單例方法),它甚至可以作到從子類別實例呼叫父類別中已被重新定義的方法。例如:
這感覺有點違反物件導向中多型的概念,一般來說,既然你已重新定義了方法,操作子類別實例的方法時應該就是被重新定義的方法,而不是父類別方法。不過這也開啟了另一個功能性,
因為 Ruby 中無法限制某個類別無法被繼承或無法被重新定義,為了確認執行某方法時,該方法一定是沒被重新定義過的方法,就可以使用這種功能性。例如:
如果願意,你也可以呼叫
to_proc 將一個 Method 轉換為 lambda。例如:
一個應用的例子,可以在 建構、初始與消滅 中看到:
執行結果如下:
Preface
Ruby 中,方法本身並不直接以物件方式存在,然而可以透過 method 方法取得 Method 實例。例如:
取得 Method
可以看到,取得的 Method 實例,self 綁定的物件是 s,可以取得 Method 實例的應用之一,就是當你的物件公開介面不一致,但又想以統一方式取得呼叫結果時。例如:
- class Some
- def initialize(value)
- @value = value
- end
- def doSome(value)
- @value - value
- end
- end
- class Other
- def initialize(amount)
- @amount = amount
- end
- def doOther(amount)
- @amount - amount
- end
- end
- def utility(p, mth)
- mth.call(p)
- end
- s = Some.new(100)
- o = Other.new(200)
- puts utility(10, s.method(:doSome)) # 90
- puts utility(10, o.method(:doOther)) # 190
- class Some
- def initialize(value)
- @value = value
- end
- def doSome(value)
- @value - value
- end
- end
- s1 = Some.new(10)
- s2 = Some.new(20)
- puts s1.doSome(5) # 5
- unbind_mth = s1.method(:doSome).unbind
- puts unbind_mth.bind(s2).call(5) # 15
- class Some
- def initialize(value)
- @value = value
- end
- def doSome(value)
- @value - value
- end
- end
- s1 = Some.new(10)
- s2 = Some.new(20)
- unbind_mth = Some.instance_method(:doSome)
- puts unbind_mth.bind(s1).call(5) # 5
- puts unbind_mth.bind(s2).call(5) # 15
- class Some
- def initialize(value)
- @value = value
- end
- def doSome(value)
- @value - value
- end
- end
- class C_Some < Some
- def doSome(value)
- @value + value
- end
- end
- s = Some.new(10)
- c_s = C_Some.new(20)
- unbind_mth = Some.instance_method(:doSome)
- puts unbind_mth.bind(s).call(5) # 5
- puts unbind_mth.bind(c_s).call(5) # 15,而不是 25,因為呼叫了父類別的 doSome
- puts c_s.doSome(5) # 25
- class Some
- def initialize(value)
- @value = value
- end
- def doSome(value)
- @value - value
- end
- end
- # 一定呼叫Some的doSome
- def do_some(s, v)
- mth = Some.instance_method(:doSome).bind(s)
- mth.call(v)
- end
- class C_Some < Some
- def doSome(value)
- @value + value
- end
- end
- puts do_some(Some.new(10), 5) # 5
- puts do_some(C_Some.new(20), 5) # 15
一個應用的例子,可以在 建構、初始與消滅 中看到:
- class Some
- def initialize(value)
- @value = value
- ObjectSpace.define_finalizer(self,
- self.method(:finalize).to_proc)
- end
- def finalize(object_id)
- puts "Destroy #{object_id} Some(#{@value})...."
- end
- end
- Some.new(10)
- Some.new(20)
- Some.new(30)
- ObjectSpace.garbage_collect # 提示 GC
沒有留言:
張貼留言