go定義接口以及類怎麼使用接口

go定義接口以及類怎麼使用接口

 

多態是指代碼可以根據類型的具體實現採取不同行爲的能力。如果一個類型實現了某個接口,所有使用這個接口的地方,都可以支持這種類型的值。

  • 接口是用來定義行爲的類型。這些被定義的行爲不由接口直接實現,而是通過方法由用戶定義的類型實現。如果用戶定義的類型實現了某個接口類型聲明的一組方法,那麼這個用戶定義的類型的值就可以賦給這個接口類型的值。這個賦值會把用戶定義的類型的值存入接口類型的值。對接口值方法的調用會執行接口值裏存儲的用戶定義的類型的值對應的方法。因爲任何用戶定義的類型都可以實現任何接口,所以對接口值方法的調用自然就是一種多態。

下面將創建一個用戶定義結構體並實現一個發送接口:

package main

import "fmt"

// 定義一個notifier接口
// 通知類行爲的一個接口
type notifier interface {
    notify()
}

// 定義一個用戶類
type user struct {
    name string
    email string
}
 
// nofity是使用指針接收者實現的方法
func (u *user) notify()  {
    fmt.Print("發送一條郵件給%s<%s>", u.name, u.email)
}

func main() {
    // 創建一個用戶並複製
    user := user{"小明", "1001**@qq.com"}
    sendNotification(&user)
}

func sendNotification(n notifier)  {
    n.notify()
}

注意:這裏傳遞給sendNotification方法的用戶定義結構體值user,是使用引用的方式傳遞的。因爲類在實現接口的時候傳遞的參數是引用類型:(u *user),如果你是使用值傳遞的話,編輯器會報錯。

./demo.go:25:18: cannot use user (type user) as type notifier in argument to sendNotification:
    user does not implement notifier (notify method has pointer receiver)

 

進一步探索新問題,爲什麼上述使用值不行,使用引用可以呢?

如果你把是實現接口的傳遞參數改成值的形式而不是引用,你將會發現有所不同

// nofity是使用指針接收者實現的方法
func (u user) notify()  {
    fmt.Print("發送一條郵件給%s<%s>", u.name, u.email)
}

// 創建一個用戶並複製
user := user{"小明", "1001**@qq.com"}
sendNotification(user)
sendNotification(&user)

你將會發現,使用引用的方式調用跟使用值的方式調用,編譯器都不會報錯,這是爲什麼?

  • 因爲底層實現是如果使用指針來實現一個接口(u *user),那麼只有指向那個類型(user)的指針才能實現對應的接口。
  • 如果使用值來實現一個接口,那麼那個類型(user)的值和指針都能夠實現對應的接口。

注意:使用指針實現接口和使用值實現接口有個區別在於,指針是指向內存同一塊地址的,所以通過指針傳遞的參數,在函數體內執行結構體的改變會影響函數外的用戶類型值,而使用值傳遞則不會 ,這也是在使用指針和使用值的不同場景選擇的一個區別其中之一。

使用值:

package main

import "fmt"

// 定義一個notifier接口
// 通知類行爲的一個接口
type notifier interface {
    notify()
}

// 定義一個用戶類
type user struct {
    name string
    email string
}
 
// nofity是使用指針接收者實現的方法
func (u user) notify()  {
    u.name = "小紅"
    fmt.Print("發送一條郵件給%s<%s>", u.name, u.email)
}

func main() {
    // 創建一個用戶並複製
    user := user{"小明", "1001**@qq.com"}
    //sendNotification(user)
    sendNotification(&user) // 小明
    fmt.Println(user.name)
    sendNotification(user) // 小明
    fmt.Println(user.name)

}

func sendNotification(n notifier)  {
    n.notify()
}

使用指針:

package main

import "fmt"

// 定義一個notifier接口
// 通知類行爲的一個接口
type notifier interface {
    notify()
}

// 定義一個用戶類
type user struct {
    name string
    email string
}
 
// nofity是使用指針接收者實現的方法
func (u *user) notify()  {
    u.name = "小紅"
    fmt.Print("發送一條郵件給%s<%s>", u.name, u.email)
}

func main() {
    // 創建一個用戶並複製
    user := user{"小明", "1001**@qq.com"}
    //sendNotification(user)
    sendNotification(&user) // 小紅
    fmt.Println(user.name)

}

func sendNotification(n notifier)  {
    n.notify()
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章