本文章同时发布于:
MediumiT 邦帮忙Golang 有一个有趣的现象,就是他不像经典 OOP(如 Java)一样是透过此实例所属哪种介面
来分类,而是透过此实例有哪些行为
来分类。
举个 JAVA 的例子,虽然ACaller
、BCaller
、CCaller
都有 call function,但因为CCaller
与ACaller
、BCaller
实作的介面不同,所以程式码在doRequest(new CCaller());
会爆炸,
线上 run code
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 因为不看是从哪个介面产出,只看行为
,所以不会爆炸,
线上 run code
package mainimport "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 也是不会提前跟你说你丢错东西了
,因为如前面所说,他们行为相同嘛!