Golang 的面向对象

文章目录

        • duck typing
        • nil不一定是空接口
        • 组合代替继承
        • 接口转换回具体的类型
        • 使用switch匹配接口的原始类型

duck typing

golang中实现某个接口不需要像其它语言使用 implemet 去继承实现,而是只要你的结构体包含接口所需的方法即可

package main

import "fmt"

type Person interface {
	talk()
}

type XM struct {
}

func (receiver XM) talk() {
	fmt.Println("I am XM")
}

func main() {
	var p Person
	p = XM{}
	p.talk() // I am XM
}

nil不一定是空接口

初始化的接口是等于 nil的,接口底层其实有一个type来记录原始的struct,当某个struct赋值给接口时,接口会在type中记录该类型(就算是nil也会记录),此时接口打印出来是nil,但和nil并不相等

}

type XM struct {
}

func (X XM) talk() {
	fmt.Println("I am XM")
}

func main() {
	var p Person
	if p == nil {
		fmt.Println("var p Person is nil") //var p Person is nil
	}
	var a *XM
	if a == nil {
		fmt.Println("var a *XM is nil") //var a *XM is nil
	}

	p = a
	if p != nil {
		fmt.Println("var p != nil") //var p != nil
	}

	fmt.Println(p) // 
}

组合代替继承

通过内嵌组合来继承功能,XM匿名内嵌了Person,就具有了Person的能力

package main

import "fmt"

type Person struct {
	Name string
}

func (receiver Person) Talk() {
	fmt.Printf("I am %s \n", receiver.Name)
}

type XM struct {
	Person
}

func main() {
	var xm XM
	p := Person{Name: "Person"}
	xm.Name = "XM"
	xm.Talk() // I am XM
	p.Talk()  // I am Person
}

重写方法只需要声明一个同名方法即可

package main

import "fmt"

type Person struct {
	Name string
}

func (receiver Person) Talk() {
	fmt.Printf("I am %s \n", receiver.Name)
}

type XM struct {
	Person
}

func (receiver XM) Talk() {
	fmt.Printf("hello,I am %s", receiver.Name)
}

func main() {
	var xm XM
	xm.Name = "XM"
	xm.Talk() // hello,I am XM
}

接口转换回具体的类型

struct 转为接口,只要struct 拥有 接口的方法,即可将struct 赋值给接口,如果想将接口转回struct,可以使用 result,ok := interface.(struct), ok 代表是否能够成功转换

package main

import "fmt"

type IAnimal interface {
	Eat()
}

type Bridge struct {
}

func (b Bridge) Eat() {
	fmt.Println("I can eat")
}

func (b Bridge) Fly() {
	fmt.Println("I can fly")
}

type Fish struct {
}

func (f Fish) Eat() {
	fmt.Println("I can eat")
}

func ShowTime(animal IAnimal) {
	animal.Eat()
	if b, ok := animal.(Bridge); ok {
		b.Fly()
	}
}

func main() {
	var (
		f Fish
		b Bridge
	)
	ShowTime(f) // I can eat
	fmt.Println("--------------")
	ShowTime(b) // I can eat \n I can fly
}

ok 判断的是完全转换,就算不ok,转换后的结果也可以调用struct的方法,但是不建议这么做

package main

import "fmt"

type IAnimal interface {
	Eat()
}

type Bridge struct {
	Name string
}

func (b Bridge) Eat() {
	fmt.Println(b.Name + "I can eat")
}

func (b Bridge) Fly() {
	fmt.Println(b.Name + "I can fly")
}

type Fish struct {
	Name string
}

func (f Fish) Eat() {
	fmt.Println(f.Name + "I can eat")
}

func ShowTime(animal IAnimal) {
	animal.Eat()
	b, ok := animal.(Bridge)
	fmt.Println(ok)
	b.Fly()
}

func main() {
	f := Fish{Name: "fish"}
	b := Bridge{Name: "bridge"}
	ShowTime(f)
	// fishI can eat
	// false
	// I can fly
	fmt.Println("--------------")
	ShowTime(b)
	//bridgeI can eat
	// true
	//bridgeI can fly
}

使用switch匹配接口的原始类型

struct.(type) 可以获取接口的原始类型,但是只能在switch中使用

package main

import "fmt"

type IAnimal interface {
	Eat()
}

type Bridge struct {
	Name string
}

func (b Bridge) Eat() {
	fmt.Println(b.Name + "I can eat")
}

func (b Bridge) Fly() {
	fmt.Println(b.Name + "I can fly")
}

type Fish struct {
	Name string
}

func (f Fish) Eat() {
	fmt.Println(f.Name + "I can eat")
}

func ShowTime(animal IAnimal) {
	switch animal.(type) {
	case Fish:
		fmt.Println("原先是Fish")
	case Bridge:
		fmt.Println("原先是Bridge")
	}
}

func main() {
	var (
		f Fish
		b Bridge
	)
	ShowTime(f) // 原先是Fish
	ShowTime(b) // 原先是Bridge
}

你可能感兴趣的:(Golang,#,go从入门到精通,golang,开发语言,后端)