接口(interface)的使用

package main

import (
   "fmt"
   "math"
)

// ========== 接口定义语法 ========== //
// type 接口名 interface {
//     Method1(形参列表) (返回值列表)
//     Method2(形参列表) (返回值列表)
//     Method3(形参列表) (返回值列表)
//     ……(声明更多接口方法)……
// }

// ========== 实现接口方法语法 ========== //
// func (s 结构体指针) Method1(形参列表) (返回值列表) {
//     // 这里实现接口声明的Method1()方法
// }
// func (s 结构体指针) Method2(形参列表) (返回值列表) {
//     // 这里实现接口声明的Method2()方法
// }
// func (s 结构体指针) Method3(形参列表) (返回值列表) {
//     // 这里实现接口声明的Method3()方法
// }
// ……(实现更多接口方法)……

// Geometry 几何图形接口
type Geometry interface {
   Perimeter() float64 // 声明接口方法①:求周长方法
   Area() float64      // 声明接口方法②:求面积方法
}

// Rectangle 矩形
type Rectangle struct {
   Width  float64 // 宽度
   Height float64 // 高度
}

// Circular 圆形
type Circular struct {
   Radius float64 // 半径
}

// Perimeter 矩形求周长【实现Geometry接口的Perimeter()方法】
func (r *Rectangle) Perimeter() float64 {
   return (r.Width + r.Height) * 2
}

// Area 矩形求面积【实现Geometry接口的Area()方法】
func (r *Rectangle) Area() float64 {
   return r.Width * r.Height
}

// Diagonal 矩形求对角线长度
func (r *Rectangle) Diagonal() float64 {
   return math.Sqrt(r.Width*r.Width + r.Height*r.Height)
}

// Perimeter 圆形求周长【实现Geometry接口的Perimeter()方法】
func (c *Circular) Perimeter() float64 {
   return 2 * math.Pi * c.Radius
}

// Area 圆形求面积【实现Geometry接口的Area()方法】
func (c *Circular) Area() float64 {
   return math.Pi * c.Radius * c.Radius
}

func main() {
   var geometry Geometry

   geometry = &Rectangle{Width: 3, Height: 4}
   fmt.Printf("矩形(1)周长:%+v \n", geometry.Perimeter()) // 矩形(1)周长:14
   fmt.Printf("矩形(1)面积:%+v \n", geometry.Area())      // 矩形(1)面积:12
   // 重要说明:虽然geometry变量被赋值&Rectangle{Width: 3, Height: 4},但它已经声明了它是Geometry接口类型,所以想
   //           通过geometry.Width和geometry.Height获取矩形宽高是错误的,因为它根本就不是Rectangle结构体类型,它能
   //           做的只有调用接口里声明的两个方法。

   // 下面是常规的创建矩形对象,然后求该矩形的周长、面积、对角线
   rectangle := &Rectangle{Width: 3, Height: 4}
   fmt.Printf("矩形(2)尺寸:%+v * %+v \n", rectangle.Width, rectangle.Height) // 矩形(2)尺寸:3 * 4
   fmt.Printf("矩形(2)周长:%+v \n", rectangle.Perimeter())                   // 矩形(2)周长:14
   fmt.Printf("矩形(2)面积:%+v \n", rectangle.Area())                        // 矩形(2)面积:12
   fmt.Printf("矩形(2)对角线:%+v \n", rectangle.Diagonal())                  // 矩形(2)对角线:5

   geometry = &Circular{Radius: 5}
   fmt.Printf("圆形周长:%+v \n", geometry.Perimeter()) // 圆形周长:31.41592653589793
   fmt.Printf("圆形面积:%+v \n", geometry.Area())      // 圆形面积:78.53981633974483

   // 重要说明:虽然只有一个geometry变量,但是通过该变量既可以求矩形的周长和面积,也可以求圆形的周长和面积,也就是可以通过
   //           一个接口来操作不同数据类型对象,这就是多态的表现。
}

// ========== 总结 ========== //
// 1、一个结构体要实现某个接口,就必须实现该接口里声明的全部方法,有一个方法未实现都无法编译。
// 2、和其它语言不同,Go语言里的接口不能有变量或常量(Java里的接口能包含常量,但不能包含变量)。

package main

import "fmt"

// Device 定义一个名为Device的接口
type Device interface {
   Work(args ...any) any // Work 定义一个名为Work的接口方法
}

// Calculator 定义一个名为Calculator的结构体(计算器),稍后该结构体会实现Device接口的Work()方法
type Calculator struct{}

// Mobile 定义一个名为Mobile的结构体(手机),稍后该结构体会实现Device接口的Work()方法
type Mobile struct{}

// Work 计算器实现Device接口里声明的Work()方法
func (calculator *Calculator) Work(args ...any) any {
   num1, _ := args[0].(int) // 断言第1个操作数
   num2, _ := args[1].(int) // 断言第2个操作数
   sum := num1 + num2       // 求两数和
   fmt.Printf("计算器工作中:%+v + %+v = %+v \n", num1, num2, sum)
   return sum
}

// Work 手机实现Device接口里声明的Work()方法
func (mobile *Mobile) Work(args ...any) any {
   num, _ := args[0].(string)
   fmt.Printf("手机工作中:正在呼叫%+v用户 \n", num)
   return nil
}

func main() {
   var device Device

   device = &Calculator{}
   device.Work(5, 2) // 计算器工作中:5 + 2 = 7

   device = &Mobile{}
   device.Work("188********") // 手机工作中:正在呼叫188********用户
}

Copyright © 2024 码农人生. All Rights Reserved