前言
在物件導向程式中,運算子重載 (operator overloading) 是一個非必備的功能,算是一種讓物件使用的語法更簡潔的語法糖;不一定每個能實作物件的語言都有運算子重載的功能,像是 C++ 有運算子重載但 Java 則無。
Groovy 官網對運算子重載並不算特別注重,僅用一點點篇幅來介紹。在 Groovy 中,要實作運算子重載相當簡單,只要實作特定的方法 (method),就自動擁有運算子重載的功能。
實例展示
以下 Vector
物件利用運算子重載的特性實作向量加法:
class Vector {
private List arr
public Vector(Integer size) {
this.arr = []
size.times { this.arr << 0.0 }
}
public Vector(List arr) {
this.arr = []
arr.each { this.arr << it }
}
public getAt(Integer i) {
return this.arr[i]
}
public Vector plus(Vector other) {
def out = new Vector(this.arr.size())
for (def i = 0; i < out.arr.size(); i++) {
out.arr[i] = this.arr[i] + other.arr[i]
}
return out
}
}
這個物件的關鍵在於我們實作了 getAt
和 plus
兩個方法;前者用在向量中以一對 [
和 ]
以索引取值,後者用在兩物件間相加。
我們以一個簡短的外部程式來看如何使用這個物件:
def a = new Vector([1, 2, 3])
def b = new Vector([2, 3, 4])
def c = a + b // Vector addition.
assert c[0] == 3 // Element retrieving by index.
assert c[1] == 5
assert c[2] == 7
雖然這個程式很短,由這個例子可以看出,適當地使用運算子重載,的確會讓程式碼更簡潔。
結語
在本文範例中,我們重載了兩個方法,之後向量物件就可以使用相關的運算子而不需要使用函式呼叫來操作物件。運算子重載的簡潔性要在外部程式中才容易彰顯出來,讀者可看一下本範例中外部程式的部分即可了解。
然而,若在實作運算子重載時埋下 bug,除錯上也是相對困難。若這個 bug 來自第三方函式庫,除錯上會更加困難,因為程式設計師甚少會在第一時間就直接追蹤第三方函式庫的程式碼。
在實作運算子重載時,應該要符合程式人的直覺,才是好的公開界面。例如,+
(加號) 應該要用在相加 (addition) 或是相接 (concatenation) 等概念的任務上,而不要任意用在其他的用途。