在程序設計語言理論和類型理論中,多型性是利用一個符號來表示多種不同類型的能力。這一概念源於生物學的原則,表示一個有機體或物種可以擁有多種不同的形式或階段。在物件導向編程中,多型性則是提供一個介面來處理不同數據類型的實體。這樣的特性讓編程語言變得更具表現力,也讓開發者能夠編寫更為通用和靈活的代碼。
多型性有多種形式,其中包括:臨時多型、參數多型和子類型。
臨時多型是指特定的多型函數可以應用於不同類型的參數,但其表現根據被應用的參數類型而異,這在某些情況下也稱作函數重載或運算子重載。在 Java 語言中的範例中,透過 Add 函數可以看到不同類型(整數與字符串)的運用,但在編譯器中,它們依然是完全不同的函數。這種情況在動態類型語言中更為複雜,因為正確的函數必須在運行時才能確定。
另一方面,參數多型允許函數或數據類型以通用的方式編寫,使其能夠無視於具體類型的情況下均能正常運行。這是一種增加語言表現力的方式,同時保持完整的靜態類型安全。
參數多型無處不在於函數式編程中,通常簡單稱為「多型」。
這種多型性並非僅為函數所有,還適用於數據類型。這裡的一個範例是在 Haskell 中對於帶參數的空列表資料類型和兩個參數多型函數的定義。
在子類型的情況下,一些語言採用子類型的概念來限制某個多型情況下可用的類型範圍。這使得函數可以被定義為接受特定類型的對象,也能正確處理屬於其子類型的對象。這種關係可以用 S <: T 表示,反之則為 T :> S。
例如,在 Java 中,貓和狗被視為寵物的子類型。若您呼叫 letsHear() 方法,則無論是傳入寵物還是其子類型,都能正常運作。
隨著編程語言的發展,許多現代語言都引入了多型性。以 C++ 中的模板、Java 中的泛型為例,它們使開發者能編寫更冗餘度低、適用於更多類型的代碼。
另外,相對於參數多型和子類型,多型的具體實現也可分為靜態多型和動態多型。靜態多型在編譯時進行選擇,而動態多型則通常在運行時根據對象的類型進行選擇。靜態多型的執行速度更快,且無需動態調用的開銷,但動態多型則在靈活性上有著更大的優勢。
在許多流行的物件導向編程語言中,常是透過繼承來實現子類型多型,並通過虛擬表來維護多型接口。
由於多型性在設計模式及其實現方式中扮演著重要角色,它使得開發者能夠更容易地應對變化和擴展需求。然而,隨著時間的推移,對於多型的理解和應用也在不斷地演變。隨著編程語言的多樣性和技術的進步,這一概念又會如何推進和改變呢?