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 的内容也到此结束,有任何问题欢迎与我告知 :)
此篇文章同步更新於 我的部落格


<<:  RISC-V: I-type 移位指令

>>:  DAY 12 - 时钟怪 (1)

Day 6 : HTML - 网页排版超强神器part_2,CSS grid到底是什麽?

上篇介绍了CSS Flex,这篇想来聊聊CSS grid到底是什麽东西 这里想先给大家一个观念: F...

【Day27】反馈元件 - Progress circle

元件介绍 Progress circle 跟上一篇 Progress bar 一样是能够展示当前进度...

JS 17 - 继承和浏览器的小问题

大家好! 昨天我们成功使用建构式建立一个新物件。 今天我们要实作的就是,在物件原型中新增共用方法。 ...

【D3】发现厨房不能用,需要更换厨房环境: 使用Python 3.8

前言 以为很顺畅的,结果发现Python 3.9无法支援,那就只好用3.8罗!因为采了不小的雷,因此...

Day05-Variables

前言 在我们之前的练习都只有使用var宣告变数,其实还有其它两个宣告方式可以使用。 接下来我们会学习...