iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0

有一個東西不受資料型別的限制,還能讓同一個函式收到不同型別傳來的值。
他是誰?

Interfaces and other types

https://ithelp.ithome.com.tw/upload/images/20230922/2014815772FPuakFX0.png

Interface

Interface 是一個定義一組方法的命名型態,任何類型只要實現了這些方法,就被視為實現了該 Interface 。這使得不同的類型可以用相同的方式進行操作。

假設你在一個火車站,有不同種類的火車(不同類型的對象)像是自強號、莒光號、...要進站(被用在某個程式碼中)。

火車站有統一的 月台 ,我們將月台想像成 Interface,每種火車都需要停在這個月台上,並且必須具備某些基本特徵,例如:能夠開車、停車、回報目的與狀況...等。這個月台定義了所有火車 共享 的操作,但不關心具體火車的型號。

舉例:

package main

import "fmt"

// 定義一個月台 (interface)
type TrainPlatform interface {
    StartRunning()
    StopRunning()
    ReportDestination(string)
}

// 定義區間車的結構
type RegularTrain struct {
    Name string
}

// 
func (t RegularTrain) StartRunning() {
    fmt.Printf("%s 開車!\n", t.Name)
}

// 
func (t RegularTrain) StopRunning() {
    fmt.Printf("%s 停車 !\n", t.Name)
}

// 報告目的
func (t RegularTrain) ReportDestination(destination string) {
    fmt.Printf("%s 即將到站 %s!\n", t.Name, destination)
}

func main() {
    trainA := RegularTrain{Name: "區間特快"}

    trainA.StartRunning()

    trainA.ReportDestination("彰化")

    trainA.StopRunning()
}

區間特快 開車!
區間特快 即將到站 彰化!
區間特快 停車 !

Conversions

有一個溫度,以攝氏度表示,但你需要將其轉換為華氏度。這是一個常見的數據轉換。攝氏度到華氏度的轉換公式如下:
華氏度 = (攝氏度 × 9/5) + 32

package main

import "fmt"

func main() {
	celsius := 25.0                      // 攝氏度
	fahrenheit := (celsius * 9 / 5) + 32 // 轉換為華氏度
	fmt.Printf("攝氏 %.2f 度 = 華氏 %.2f 度\n", celsius, fahrenheit)
}
攝氏 25.00 度 = 華氏 77.00 度

Interface conversions and type assertions

Interface Conversions 將一個實現了某介面的具體類型轉換為該介面的操作。
舉例:
有一台電腦主機,主機有多個 USB 接口可以接受 不同種類 的USB 設備,例如 USB 滑鼠、USB 鍵盤、USB 影印機...等等。
這裡的USB接口就可以被視為一個 interface ,它定義了一組標準方法(例如數據傳輸、電源供應等等),這些方法可以被不同種類的 USB 設備連接。
舉例:

package main

import "fmt"

// 定義 USB 設備 interface
type USBDevice interface {
	Connect()
	Disconnect()
}

// 定義 USB 滑鼠
type USBMouse struct {
	Name string
}

func (m USBMouse) Connect() {
	fmt.Printf("%s 滑鼠已連線。\n", m.Name)
}

func (m USBMouse) Disconnect() {
	fmt.Printf("%s 滑鼠離開連線\n", m.Name)
}

// 定義 USB 鍵盤
type USBKeyboard struct {
	Name string
}

func (k USBKeyboard) Connect() {
	fmt.Printf("%s 鍵盤已連線\n", k.Name)
}

func (k USBKeyboard) Disconnect() {
	fmt.Printf("%s 鍵盤離開連線\n", k.Name)
}

func main() {
	mouse := USBMouse{Name: "Logitech"}
	keyboard := USBKeyboard{Name: "Dell"}

	devices := []USBDevice{mouse, keyboard}

	for _, device := range devices {
		device.Connect()
		device.Disconnect()
	}
}
Logitech 滑鼠已連線。
Logitech 滑鼠離開連線
Dell 鍵盤已連線
Dell 鍵盤離開連線

Type Assertions 用於檢查介面值的 實際存儲類型 ,並將其轉換為該具體類型。

package main

import "fmt"

// 定義一個介面叫做Shape
type Shape interface {
    Area() float64
}

// 定義一個矩形結構
type Rectangle struct {
    Width  float64
    Height float64
}

// 實現Shape介面的Area方法
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func main() {
    rectangle := Rectangle{Width: 5, Height: 3}

    // 將Rectangle實例轉換為Shape介面
    var shape Shape
    shape = rectangle

    // 使用 Type Assertions 檢查介面值的實際類型並取得具體類型的值
    if r, ok := shape.(Rectangle); ok {
        fmt.Printf("矩形的寬度:%f\n", r.Width)
    } else {
        fmt.Println("這不是一個矩形。")
    }
}
矩形的寬度:5.000000

Generality

Generality 指的是 Interface 提供的方式用来描述對象的行為,而不考慮型別。這允許不同型別的對應相同的 Interface ,可以用一致的方式進行操作和處理。
舉例:

package main

import "fmt"

// 定義一個通用的 Shape interface
type Shape interface {
	Area() float64
}

// 定義一個矩形結構體
type Rectangle struct {
	Width  float64
	Height float64
}

func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

type Circle struct {
	Radius float64
}

func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

func main() {
	rectangle := Rectangle{Width: 5, Height: 3}
	circle := Circle{Radius: 2}

	// 使用通用的 Shape interface 来計算面積
	shapes := []Shape{rectangle, circle}

	for _, shape := range shapes {
		area := shape.Area()
		fmt.Printf("面積:%f\n", area)
	}
}
面積:15.000000
面積:12.560000

碎語

Interface 為我們提供了一種通用的方式來描述不同對象的行為,就像 Platform 9¾ 為麻瓜們提供了通往霍格華茲的道路一樣。
(都入秋了為什麼還這麼熱!


上一篇
06 | 又回到最初的起點
下一篇
08 | 誰真的需要博愛座?
系列文
Go 語言學習手札30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言