第 12 天要来介绍 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 的内容也到此结束,有任何问题欢迎与我告知 :)
此篇文章同步更新於 我的部落格
上篇介绍了CSS Flex,这篇想来聊聊CSS grid到底是什麽东西 这里想先给大家一个观念: F...
元件介绍 Progress circle 跟上一篇 Progress bar 一样是能够展示当前进度...
大家好! 昨天我们成功使用建构式建立一个新物件。 今天我们要实作的就是,在物件原型中新增共用方法。 ...
前言 以为很顺畅的,结果发现Python 3.9无法支援,那就只好用3.8罗!因为采了不小的雷,因此...
前言 在我们之前的练习都只有使用var宣告变数,其实还有其它两个宣告方式可以使用。 接下来我们会学习...