簡介
方法鏈(method chaining)是面向對象的程式語言中的一種常見語法,可以讓開發者在只引用對象一次的情況下,對同一個對象進行多次方法調用。
舉個例子:
假設我們有一個Foo類,其中包含有兩個方法——bar和baz。
我們創建一個Foo類的實例:
1 | foo = Foo() |
如果不使用方法鏈,要想連續調用對象foo的bar和baz方法的話,我們得這樣做:
1 2 | foo.bar() # Call method bar() on object foo. foo.baz() # Call method baz() on object foo. |
如果使用方法鏈的話,我們就能這樣實現: foo.bar().baz()
方法鏈的優勢
方法鏈的一個好處,是可以減少你使用對象名的次數。調用的方法越多,能夠減少的次數就越多。因此,這個方法也能一定程度上減少需要閱讀、測試、調試、維護的代碼數量。這個好處不大,但也是有用的。
1. 讓調用過程更接近自然語言。
2. 把原本參數列表複雜的方法化作多個參數列表簡單的方法來使用。
3. 減少不必要的代碼量。
這個三點都是有益於開發的,所以方法鏈的存在很有意義。
請注意,方法鏈的一個限制是,只能用在不需要返回其他值的方法上,因為你需要返回self對象。即使Python支持用一個return語句返回多個值,也可能無法解決這個問題。
Python中方法鏈的套用
下面是在Python中實現方法鏈的一個示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Person: def name(self, value): self.name = value return self def age(self, value): self.age = value return self def introduce(self): print "Hello, my name is", self.name, "and I am", self.age, "years old." person = Person() person.name("EarlGrey").age(21).introduce() # => Hello, my name is EarlGrey and I am 21 years old. |
上面那種實現可能太簡單了。更加現實的方法鏈使用方法:編寫一個字元串處理程式string_processor.py,支持方法鏈。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import copy class StringProcessor(object): ''' A class to process strings in various ways. ''' def __init__(self, st): '''Pass a string for st''' self._st = st def lowercase(self): '''Make lowercase''' self._st = self._st.lower() return self def uppercase(self): '''Make uppercase''' self._st = self._st.upper() return self def capitalize(self): '''Make first char capital (if letter); make other letters lower''' self._st = self._st.capitalize() return self def delspace(self): '''Delete spaces''' self._st = self._st.replace(' ', '') return self def rep(self): '''Like Python's repr''' return self._st def dup(self): '''Duplicate the object''' return copy.deepcopy(self) def process_string(s): print sp = StringProcessor(s) print 'Original:', sp.rep() print 'After uppercase:', sp.dup().uppercase().rep() print 'After lowercase:', sp.dup().lowercase().rep() print 'After uppercase then capitalize:', sp.dup().uppercase().\ capitalize().rep() print 'After delspace:', sp.dup().delspace().rep() def main(): print "Demo of method chaining in Python:" # Use extra spaces between words to show effect of delspace. process_string('hOWz It GoInG?') process_string('The QUIck brOWn fOx') main() |
下面是這個程式的運行結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ python string_processor.py Original: hOWz It GoInG? After uppercase: HOWZ IT GOING? After lowercase: howz it going? After uppercase then capitalize: Howz it going? After delspace: hOWzItGoInG? Original: The QUIck brOWn fOx After uppercase: THE QUICK BROWN FOX After lowercase: the quick brown fox After uppercase then capitalize: The quick brown fox After delspace: TheQUIckbrOWnfOx |
綜上,我們可以發現,方法鏈有其用處,不過過度使用可能不太好。
jQuery中方法鏈的套用
目測對於方法鏈用得最多的,應該就是jQuery了。
代碼如下:
// chaining
$("#person").slideDown('slow')
.addClass('grouped')
.css('margin-left', '11px');
我們可以用這樣的用法來調用這個。
jQuery嚴重依賴於連結。這使得它很容易調用的幾個方法相同的選擇。這也使得代碼更清晰和防止執行相同的選擇幾次(提高性能)。沒有方法鏈的時候則是下面的樣子
代碼如下:
var p = $('#person');
p.slideDown('slow');
p.addClass('grouped');
p.css('margin-left', '11px');
看上去和設計模式中的builder很像,不同的是,這裡的p是方法,而不是一個類。
Javascript中方法鏈的套用
Javascript方法鏈示例
在之前我們說到Javascript高階函式的時候,說到的print('Hello')('World'),而這種用法的結果可能會變成這樣子。
代碼如下:
function f(i){
return function(e){
i+=e;
return function(e){
i+=e;
return function(e){
alert(i+e);
};
};
};
};
f(1)(2)(3)(4); //10
代碼如下:
var func = (function() {
return{
add: function () {
console.log('1');
return{
result: function () {
console.log('2');
}
}
}
}
})();
func.add().result();
實際上應該在每個function都要有個return this,於是就有了:
Func = (function() {
this.add = function(){
console.log('1');
return this;
};
this.result = function(){
console.log('2');
return this;
};
return this;
});
var func = new Func();
func.add().result();
可以將最後的兩句
var func = new Func();
func.add().result();
變成
new Func().add().result();
其他
最後作為一個迷惑的地方的小比較:
Method Chaining VS prototype Chaining
原型鏈與方法鏈在某些方面上是差不多的,不同的地方或許在於
原型鏈是需要用原型
方法鏈則是用方法
1.原型鏈是需要用原型
2.方法鏈則是用方法