在Java 中,重載(overload)和重寫(override)是用來表現多態性的兩種重要方式。override 也有譯作“覆蓋”、“覆寫”。Java 中稱作“覆寫”比較恰當。
重載方法是指一個類中,方法名相同、參數列表不同的幾個方法,調用時根據不同的參數調用不同的方法。方法重載與返回類型無關。
覆寫方法是指子類有一個方法,方法名、參數列表、返回類型與父類的某個方法完全一致。調用時會調用子類的方法,而屏蔽掉父類的同名方法。需要注意的是,子類覆寫的方法,其可訪問性一定要強於或等同於,父類被覆寫的同名方法。
覆寫發生在子類和父類之間,當然也可以是子類和父類的父類之間。重載不僅僅是發生在子類和父類之間,大多數時候,發生在同一個類中。
4.5節說到:“ Ruby語言,只有重寫,沒有其它語言具有的嚴格意義上的重載。” 下面仔細分析 Ruby 爲何沒有重載,只有重寫。
Java 的重載, 參數列表不同有三種形式。
一.參數個數不同
sum(int a)
sum(int a ,int b)
二.參數個數相同,參數類型不同
sum(int a)
sum(float a)
三.參數個數相同,參數類型相同,對應位置不同
sum(int a , float b)
sum(float a ,int b)
Ruby支持缺省參數,我們看程序 E6.1-1.rb :由於缺省參數和可變參數,參數個數不同而產生的重載,在Ruby中不再有效。Ruby語言中,定義方法時,不指定參數類型,因此第二種形式的重載也不存在。第三種形式的重載,實際是第二種形式的演化,所以,也就不存在了。綜上所述,Ruby語言,沒有方法的重載。
- def sum( a, b=5 )
- a+b
- end
- puts sum(3,6) # => 9
- puts sum(3) # => 8
調用sum(3,6) 與 調用sum(3) 在Java中是調用不同的方法,在Ruby中其實是在調用同一個方法。
Ruby還支持可變參數,我們看程序 E6.1-2.rb :
- # E6.1-2.rb
- def sum( *num )
- numSum = 0
- num.each { |i| numSum+=i }
- return numSum
- end
- puts sum() # => 0
- puts sum(3,6) # => 9
- puts sum(1,2,3,4,5,6,7,8,9) # => 45
方法的重寫,我們在4.4節和4.5節已經看到了。Worker類與Student類繼承自Person類,並且各自重寫了Person類的talk方法。
這是在子類和父類之間,如果在同一個類中寫兩個同名方法呢?看程序 E6.1-3.rb :
- # E6.1-3.rb
- def talk (a)
- puts "This is talk version 1."
- end
- def talk (a,b=1)
- puts "This is talk version 2."
- end
- talk (2) # => This is talk version 2.
- talk (2,7) # => This is talk version 2.
總是寫在後面的方法被執行。
從上面三個小程序可知:在Ruby中,我們說覆寫是指重寫,我們說重載也是指重寫。
Java 和 C++ 是靜態語言,程序代碼運行中不可以再改變類的屬性、方法,爲了更好地表現面向對象的多態特徵,所以用覆寫和重載來加強程序的靈活性,在程序運行的時候,動態地選擇要使用的方法, 完成後期綁定。而 Ruby 是動態語言,可以隨時改變類的屬性、方法,所以覆寫和重載的重要性就降低了。仔細體會一下,一者是增大可選擇性,一者是隨時修改。
完整閱讀,請看我寫的 Ruby語言中文教程all in one