位元詩人 [Groovy] 程式設計教學:藉由運算子重載 (Operator Overloading) 使程式碼更簡潔

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

在物件導向程式中,運算子重載 (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
    }
}

這個物件的關鍵在於我們實作了 getAtplus 兩個方法;前者用在向量中以一對 [] 以索引取值,後者用在兩物件間相加。

我們以一個簡短的外部程式來看如何使用這個物件:

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) 等概念的任務上,而不要任意用在其他的用途。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。