1. 程式人生 > >(三十五)golang--面向物件之多型

(三十五)golang--面向物件之多型

多型:變數具有多種形態,可以用統一的介面來呼叫不同的實現。

介面體現多型特徵:

(1)多型引數:之前所講的Usb介面案例,既可以接受手機變數,也可以接受相機變數,就體現了usb介面的多型;

(2)多型陣列:

package main

import (
    "fmt"
)

type usb interface {
    start()
    stop()
}

type phone struct {
    name string
}

func (p phone) start() {
    fmt.Println(p.name, "手機開始工作")
}

func (p phone) stop() {
    fmt.Println(p.name, "手機停止工作")
}

type camera struct {
    name string
}

func (c camera) start() {
    fmt.Println(c.name, "相機開始工作")
}

func (c camera) stop() {
    fmt.Println(c.name, "相機停止工作")
}

type computer struct {
}

func (co computer) working(usb usb) {
    usb.start()
    usb.stop()
}

func main() {
    var usbArr [3]usb
    usbArr[0] = phone{"小米"}
    usbArr[1] = phone{"vivo"}
    usbArr[2] = camera{"尼康"}
    fmt.Println(usbArr)
    for i := 0; i < len(usbArr); i++ {
        usbArr[i].start()
        usbArr[i].stop()
    }
}

我們以前講到,陣列是隻能儲存同一種類型的資料,利用多型陣列,就可以儲存不同的型別了;

如何將一個介面變數賦值給一個自定義型別的變數?使用型別斷言

型別斷言:由於介面是一般型別,不知道具體型別,如果要轉成具體型別,就需要使用型別斷言;要保持原來空介面指向的資料型別和斷言的資料型別一致;

為了避免輸出panic報錯,可以進行斷言判斷;

型別斷言實踐一:

我們給phone中加入一個方法call(),在呼叫usb變數時,usb.call(),肯定是不對的,因為usb可能是phone,也可能是camera,而camera是沒有這個函式的,因此,在呼叫的時候用型別斷言。

package main

import (
    "fmt"
)

type usb interface {
    start()
    stop()
}

type phone struct {
    name string
}

func (p phone) start() {
    fmt.Println(p.name, "手機開始工作")
}

func (p phone) call() {
    fmt.Println(p.name,"手機在打電話")
}

func (p phone) stop() {
    fmt.Println(p.name, "手機停止工作")
}

type camera struct {
    name string
}

func (c camera) start() {
    fmt.Println(c.name, "相機開始工作")
}

func (c camera) stop() {
    fmt.Println(c.name, "相機停止工作")
}

type computer struct {
}

func (co computer) working(usb usb) {
    usb.start()
    //如果usb還指向phone的結構體變數,則還需要呼叫call方法
    if phone, ok := usb.(phone); ok {
        phone.call()
    }
    usb.stop()
}

func main() {
    var usbArr [3]usb
    usbArr[0] = phone{"小米"}
    usbArr[1] = phone{"vivo"}
    usbArr[2] = camera{"尼康"}
    var com computer
    fmt.Println(usbArr)
    for i := 0; i < len(usbArr); i++ {
        com.working(usbArr[i])
    }
}

型別斷言實踐2:迴圈判斷輸入引數的型別

package main

import (
    "fmt"
)

type student struct {
    name string
}

func typeJudge(items ...interface{}) {
    for index, x := range items {
        switch x.(type) {
        case bool:
            fmt.Printf("第%v個引數是bool型別,值是%v\n", index, x)
        case int, int32, int64:
            fmt.Printf("第%v個引數是整數型別,值是%v\n", index, x)
        case float32:
            fmt.Printf("第%v個引數是float32型別,值是%v\n", index, x)
        case float64:
            fmt.Printf("第%v個引數是float64型別,值是%v\n", index, x)
        case string:
            fmt.Printf("第%v個引數是string型別,值是%v\n", index, x)
        case student:
            fmt.Printf("第%v個引數是student型別,值是%v\n", index, x)
        case *student:
            fmt.Printf("第%v個引數是*student型別,值是%v\n", index, x)
        default:
            fmt.Printf("第%v個引數型別不確定,值是%v\n", index, x)
        }
    }
}

func main() {
    var n1 float32 = 1.1
    var n2 float64 = 1.2
    var n3 int32 = 1
    var name string = "tom"
    var n5 bool = true

    stu1 := student{"jack"}
    stu2 := &student{"bob"}

    typeJudge(n1, n2, n3, name, n5, stu1, stu2)
}