本文章同時發佈於:
Golang 有一個有趣的現象,就是他不像經典 OOP(如 Java)一樣是透過此實例所屬哪種介面
來分類,而是透過此實例有哪些行為
來分類。
舉個 JAVA 的例子,雖然ACaller
、BCaller
、CCaller
都有 call function,但因為CCaller
與ACaller
、BCaller
實作的介面不同,所以程式碼在doRequest(new CCaller());
會爆炸,
interface Caller {
public void call();
}
interface OtherCaller {
public void call();
}
class ACaller implements Caller {
public ACaller() {
}
public void call() {
System.out.printf("Call API A");
}
}
class BCaller implements Caller {
public BCaller() {
}
public void call() {
System.out.printf("Call API B");
}
}
class CCaller implements OtherCaller {
public CCaller() {
}
public void call() {
System.out.printf("Call API C");
}
}
public class Main {
public static void main(String[] args) {
doRequest(new ACaller());
doRequest(new BCaller());
// 爆炸!雖然行為相同的介面不同!
doRequest(new CCaller());
}
public static void doRequest(Caller caller) {
caller.call();
}
}
而 Golang 因為不看是從哪個介面產出,只看行為
,所以不會爆炸,
package main
import "fmt"
type Caller interface {
call()
}
type ACaller struct {}
func (c *ACaller) call () {
fmt.Println("Call API A")
}
type BCaller struct {}
func (c *BCaller) call () {
fmt.Println("Call API B")
}
type CCaller struct {}
func (c *CCaller) call () {
fmt.Println("Call API C")
}
func doRequest(c Caller) {
c.call()
}
func main () {
doRequest(&ACaller{})
doRequest(&BCaller{})
// 不會爆炸!因為Golang只看行為是否相同!
doRequest(&CCaller{})
}
這使 Golang 增加了很多彈性,
在 JAVA 中雖然狗會發出聲音,機車也會發出聲音,但你沒辦法把他們用同個 function 來使他們一起唱交響樂,因為不是同個 interface 產出。
但 Golang 可以這麼做,但你要小心,如果你期望是用狗來唱歌,但不小心丟了機車至 此 function,那 Golang 也是不會提前跟你說你丟錯東西了
,因為如前面所說,他們行為相同嘛!