Java中的多態
多態與HoFs
朋友們好久不見啊,最近筆者同時在寫腳本型語言——
JavaScript,和工業級的面向對象語言——Java。 在寫程式碼的同時呢,也會思考這些語言的不同。今天就拿 Java 中的多態,來談一談吧!
概念
多態(Polymorphism)
多態性的核心是多種表現形式。在 Java中,多態性是指對象可以擁有多種形式或者說類型。在面向對象的編程中,多態與如何將一個對象視為其自身類的實例,或者是它的父類的實例,又或者父類的父類的實例等相關。
上面那段話或許有些抽象,還是讓我們舉個例子吧:
假設我們擁有兩個類:
SLList 類和 VengefulSLList 類,
其中 VengefulSLList 類繼承自 SLList 類。並覆寫(override)了, removeLast 方法(method)。
我們運行以下程式碼:

結果:
sl.addLast(50) ; //VengefullSLList沒有覆寫,調用的是父類(即SLList)的方法
sl.removeLast(); //調用的是自己覆寫的 removeLast( ) 方法!
再看一個例子:
public static void main(String[] args){
VengefullSLList<Integer> s1 = new VengefullSLList<>(9);
SLList<Integer> s2 = new SLList<>(8);
s1.removeLast(); // 調用覆寫的方法
s2.removeLast(); // 調用 SLList類的方法
}
事實說明,即使是調用同一個方法,根據對象的不同,其產生的結果是多種多樣的!而且,每個對象也能展現不同的類型。
HoF
Higher Order Function: A function that treats another function as data.
高級函數: 是指一個函數把其他函數當成數據。
例如 JavaScript 中的 function 就是一個 對象,可以當做參數傳遞。
在 Python 中我們可以這樣來運用它:
def tenX(x):
return 10*x
def do_twice(f, x):
return f(f(x))
print(do_twice(tenX, 2))
# 200
然而在 Java 中我們沒見過這樣的用法,這是因為在 jdk8 以前 Java是禁止將函數當參數傳遞的!
問題
那麼問題來了,如果 Java不允許 HoF 的存在,我們怎麼解決這類問題呢?
例如比較大小:
def print_larger(x, y, compare, stringify):
if compare(x, y):
return stringify(x)
return stringify(y)
# HoF 模式
def print_larger(x, y):
if x.largerThan(y):
return x.str()
return y.str()
# Subtype Polymorphism 模式
# 子類的多樣性
我們主要說說第二種方式:
在程式碼中,我們為每個對象提供了 largerThan()的方法,通過調用它實現比大小。但是在 Java 中,如果我們想要實現比較各種類型的對象大小的方法呢?比如說,我們要比較企鵝的大小,我們就要實現 企鵝類的 largerThan()方法。我們要比較海豹的大小,就要實現 海豹類的largerThan()方法,。。。。。。
我們發現如果直接實現子類的方法,我們無法實現通用的比較方案,在 C++中我們可以使用重載操作符,在JS中我們可以傳入 compare函數。那麼我們在Java中如何實現呢?
Comparable介面
前面我們提到了多態,有時候我們調用同名的方法,也會得到不同的結果。我們可以利用這種特性,來構造一個 compareTo() 方法。
在 Java中,我們有一個介面(interface) , 叫做 Comparable 。

它規定了所有要實現該介面的類,要實現它的 compareTo(T obj) 方法。
通過介面,我們也可以巧妙的實現,對各種類型的對象,提供一個通用的解決方法!
比如我們要實現一個自己的 Util類,裡面有一個 max(Comparable[] items )方法,它的功能是,返回給定的對象數組中最大的那個對象。
這裡我們使用 Dog類做演示:

項目目錄:
我們實現了三個類,分別是 Dog,Util,Util
程式碼如下:
public class Dog implements Comparable<Dog> {
private int size; // 尺寸
private String name; // 名字
public Dog(){}
public Dog(int size, String name){
this.name = name;
this.size = size;
}
public void bark(){
System.out.println("My name is "+this.name+"!");
}
@Override
public int compareTo(Dog other) { // 覆寫的compareTo()方法
return this.size - other.size;
}
}
public class Util {
public static Comparable max(Comparable[] items){
int maxIndex=0;
// 遍歷找出size最大的狗
for (int i = 0; i < items.length; i++) {
int cmp = items[i].compareTo(items[maxIndex]);
if(cmp>0){
maxIndex = i;
}
}
return items[maxIndex];
}
}
public class LaunchDog {
public static void main(String[] args) {
Dog alice = new Dog(8,"alice");
Dog ben = new Dog(12,"ben");
Dog karn = new Dog(6,"karn");
Dog[] dogs = new Dog[]{alice,ben,karn};
// 調用 max() 方法
Dog d =(Dog) Util.max(dogs);
d.bark();
}
}
最後的輸出結果為:
My name is ben!
總結
通過分析以上程式碼,我們發現只要是 實現了 Comparable 介面的類都可以輕鬆使用 Util類中的 max() 方法選出最大的項。而在 Java 中我們的 集合框架就實現了 Comparable介面,拿來即用,十分方便。
所以,在項目中我們可以利用 介面(interface) , 來實現 在腳本語言中用 HoF 實現的功能。這體現了 Java的多態。
總結,Java通過提供介面 賦予了我們使用回調的能力。
To summarize, interfaces in Java provide us with the ability to make callbacks. Sometimes, a function needs the help of another function that might not have been written yet (e.g.
maxneedscompareTo). A callback function is the helping function (in the scenario,compareTo).
refer:

