iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
自我挑戰組

30 天學 Golang?Go 啦哪次不 Go系列 第 12

Day12# interface

第 12 天要來介紹 interface
那麼話不多說,我們就進入正題吧 ─=≡Σ(((っ゚∀゚)っ

interface

再開始討論 interface 前,先讓我們回憶一下 struct 及 methods,這兩個型態是 Go 用來實踐物件導向很重要的行為。

// 定義 & 屬性
type User struct {
    Id   int
    Name string
    Age  int
}

// 定義 & 行為
func (u User) greeting() string {
    return "hi, " + u.Name
}

而 interface 就是透過將不同 type 的相同行為給集合起來,在執行 interface 時不用再為各個 type 指定使用方法。

使用的方式,就讓我們派出人人都愛的貓貓狗狗吧!

type Dog struct {
	Name string
}

type Cat struct {
	Name string
}

// 讓貓貓狗狗吃吃喝喝!
func (d *Dog) eat() {
	fmt.Println(d.Name, "吃肥宅餐")
}

func (d *Dog) drink() {
	fmt.Println(d.Name, "喝肥宅水")
}

func (c *Cat) eat() {
	fmt.Println(c.Name, "吃快樂餐")
}

func (c *Cat) drink() {
	fmt.Println(c.Name, "喝快樂水")
}

他們都會有共同的方法可以使用,這時候就能夠把他們的共同行為透過 interface 定義起來:

貓跟狗都會吃吃喝喝 => 動物都會吃吃喝喝

既然抓到這個概念,這樣我們的 interface 就能夠用 Animal 來定義:

type Animal interface {
	eat()
	drink()
}

並且定義一個方法,讓 Cat 跟 Dog 生出的實體,透過參數傳進去:

func goEat(a Animal) {
	a.eat()
}

func goDrink(a Animal) {
	a.drink()
}

因為是 Animal interface,因此我們傳入的參數也需要是 Animal 型態,而這些被傳入的其他型別,就會把自己歸類為 Animal。

為什麼會有這樣的行為,就需要特別介紹 Duck typing 是什麼:
不是由繼承自特定的類別或實現特定的介面,而是由當前方法和屬性的集合決定。因此「當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。」

(圖片來自影集 Lucifer)

回到剛才的例子,只要能夠被丟進 Animal 類別的,就會被當作 Animal 來使用。

實際的應用就會是這樣:

package main

import "fmt"

type Animal interface {
	eat()
	drink()
}

type Dog struct {
	Name string
}

type Cat struct {
	Name string
}

func (d *Dog) eat() {
	fmt.Println(d.Name, "吃肥宅餐")
}

func (d *Dog) drink() {
	fmt.Println(d.Name, "喝肥宅水")
}

func (c *Cat) eat() {
	fmt.Println(c.Name, "吃快樂餐")
}

func (c *Cat) drink() {
	fmt.Println(c.Name, "喝快樂水")
}

func goEat(a Animal) {
	a.eat()
}

func goDrink(a Animal) {
	a.drink()
}

func main() {
	dog := Dog{Name: "MeiMei"}
	cat := Cat{Name: "BuiBui"}
	goEat(&dog)
	goDrink(&cat)
}

// => MeiMei 吃肥宅餐
//    BuiBui 喝快樂水

結尾

登愣,雖然我一開始待補,但內容從不缺席。
interface 的內容也到此結束,有任何問題歡迎與我告知 :)
此篇文章同步更新於 我的部落格


上一篇
Day11# Pointer
下一篇
Day13# defer
系列文
30 天學 Golang?Go 啦哪次不 Go20

尚未有邦友留言

立即登入留言