• ch18、面向对象编程-不一样的接口类型,一样的多态


    ch18、面向对象编程 - 不一样的接口类型,一样的多态

    1、多态

    多态:就是某一类事物的多种形态。

    Go语言中的多态是通过接口类型来实现"多态"

    package main
    
    import "fmt"
    
    // 1.定义接口
    type Animal interface {
    	Eat()
    }
    type Dog struct {
    	name string
    	age  int
    }
    
    // 2.实现接口方法
    func (d Dog) Eat() {
    	fmt.Println(d.name, "正在吃东西")
    }
    
    type Cat struct {
    	name string
    	age  int
    }
    
    // 2.实现接口方法
    func (c Cat) Eat() {
    	fmt.Println(c.name, "正在吃东西")
    }
    
    // 3.对象特有方法
    func (c Cat) Special() {
    	fmt.Println(c.name, "特有方法")
    }
    
    func main() {
    	// 1.利用接口类型保存实现了所有接口方法的对象
    	var a Animal
    	a = Dog{"旺财", 18}
    	// 2.利用接口类型调用对象中实现的方法
    	a.Eat()
    	a = Cat{"喵喵", 18}
    	a.Eat()
    	// 3.利用接口类型调用对象特有的方法
    	//a.Special() // 接口类型只能调用接口中声明的方法, 不能调用对象特有方法
    	if cat, ok := a.(Cat); ok {
    		cat.Special() // 只有对象本身才能调用对象的特有方法
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    多态优点:

    • 多态的主要好处就是简化了编程接口。它允许在类和类之间重用一些习惯性的命名,而不用为每一个新的方法命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来
    • 多态也使得代码可以分散在不同的对象中而不用试图在一个方法中考虑到所有可能的对象。 这样使得您的代码扩展性和复用性更好一些。当一个新的情景出现时,您无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法

    2、空接口与断言

    空接口可以表示任何类型(类似Java的object)

    通过断言来将空接口转换为指定类型(类似于x.(T),其中x是一个接口类型的表达式、T是一个类型)

    package empty_interface
    
    import (
    	"fmt"
    	"testing"
    )
    
    func DoSomething(p interface{}) { // 传入的是个空接口
    	if i, ok := p.(int); ok {   // 断言判断
    		fmt.Println("Integer: ", i)
    		return
    	}
    	if s, ok := p.(string); ok {
    		fmt.Println("string: ", s)
    		return
    	}
    	fmt.Println("Unknow Type.")
    }
    
    func TestEmptyInterfaceAssertion(t *testing.T) {
    	DoSomething(10)
    	DoSomething("10")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    以上方法有点繁琐,最好使用switch结构

    package empty_interface
    
    import (
    	"fmt"
    	"testing"
    )
    
    func DoSomething2(p interface{}) {
    	switch v := p.(type) {
    	case int:
    		fmt.Println("Integer: ", v)
    	case string:
    		fmt.Println("string: ", v)
    	default:
    		fmt.Println("Unknow Type.")
    	}
    }
    
    func TestEmptyInterfaceAssertion2(t *testing.T) {
    	DoSomething2(10)
    	DoSomething2("10")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3、Go接口最佳实践

    • 倾向于使用小的接口定义
    type Reader interface{
        Read(p []byte) (n int, err error)
    }
    
    type Writer interface{
        Writer(p []byte) (n int, err error)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 较大的接口定义,可以由多个小接口定义组合而成
    type ReadWriter interface {
        Reader
        Writer
    }
    
    • 1
    • 2
    • 3
    • 4
    • 只依赖于必要功能的最小接口
    type StoreData(reader Reader) error {
        ...
    }
    
    • 1
    • 2
    • 3
  • 相关阅读:
    【校招VIP】java开源框架之Zookeeper
    柯桥托业TOEIC考试和PETS哪个含金量高?
    MovieLens:一个常用的电影推荐系统领域的数据集
    4405. 统计子矩阵
    SQL 宽字节注入详解
    Metabase学习教程:视图-3
    使用 Microchip SAM9X60 OTP 存储板卡的MAC地址和序列号
    Android音视频开发-AudioTrack
    RocketMQ中生产者发消息前为啥一定要调用start()方法?
    Python 2.7 requests库POST请求体中有中文的处理方法
  • 原文地址:https://blog.csdn.net/u012558127/article/details/126152313