05.interface

[TOC]

一.接口基础

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
1.类型转换不适用于接口。
2.我们只能使用接口里面定义好的方法,未列出的不能使用。
3.类型断言像是说我知道这个变量使用接口类型Animal,但是我很确信这个Animal实际上就是Dog.
#-----------------------------------------------------------------------
package main

import "fmt"

type Animal interface{
Eat()
}

type Dog string

func (d Dog) Eat(){
fmt.Println(d,"wang wang!")
}

func (d Dog) Run(){
fmt.Println(d,"speed up!")
}

func main(){
var a Animal = Dog("旺财")
a.Eat()

// interface里面我们只定义了Eat()方法,Dog对象里我们定义了Eat()/Run()方法,此时 我们直接调用Run方法,报错如下:
// a.Run undefined (type Animal has no field or method Run)
// a.Run()

// 这里使用断言从接口里取回Dog对象的具体类型
var d Dog = a.(Dog)
d.Run()
}
#-----------------------------------------------------------------------
4.error类型像int或者string一样是一个“预定义标识符”,它不属于任何包。它是“全局块”的一部分,这意味着它在任何地方可用,不用考虑当前包信息。

5.Stringer接口
- 允许任何类型决定在输出时如何展示。让其他类型满足Stringer接口很简单,只需要定义一个返回string类型的方法。
- 只要是定义了符合stringer接口的方法,就会在执行的时候 直接被调用。
#-----------------------------------------------------------------------
package main

import "fmt"

type Gallons float64
func (g Gallons) String() string{
return fmt.Sprintf("%0.2f gal",g)
}

type Liters float64

func (l Liters) String() string{
return fmt.Sprintf("%0.2f L",l)
}


type Milliliters float64
func (m Milliliters) String() string{
return fmt.Sprintf("%0.2f mL",m)
}


type CoffeePot string

func (c CoffeePot) String() string {
return string(c)+"coffee pot"
}

func main(){
coffeePot :=CoffeePot("华为牌")
fmt.Println(coffeePot)

// 自动调用String方法
fmt.Println(Gallons(11.0202992))
fmt.Println(Liters(11.0202992))
fmt.Println(Milliliters(11.0202992))
}
#-----------------------------------------------------------------------

6.接口特性
- 接口定义只有方法
- 接口是引用类型
- 实例化时,接口不能直接使用变量,必须指向实现。
- Golang没有严格的implement关键字。
- 必须实现所有的接口方法,才叫实现接口,否则不算。
- 必须实现所有的接口方法,才叫实现接口,不限类型。
- 同一个对象可以实现多个接口。
- 接口之间可以组合、嵌套(c=a+b+c,也可以c=ab+bc)。
- 空接口=any=黑盒子。

7.类型断言
- interface{}可以容纳任何对象,因此从各种对象赋值给interface变量时可以无缝赋值。
- 从interface{}重新赋值回特定的类型,无法直接赋值。
- switch 方式
- value,ok := i.(<type>)
8.对象or指针
- 方法可以再对象上,也可以再对象指针上,在使用时,调用、功能有略微差异。
- 定义在对象上的方法无法修改对象属性,定义在对象指针上的可以。
- 对象上实现了接口的所有函数,才可以转为对应的接口对象,如果某些函数是在对象指针上,某些是在对象上,则只能用对象指针作为接口对象。
9.接口技巧
- 接口的变更,不会带来编译失败,从而导致程序出现异常。

10.善用var _ int(接口) = &io{} //接口实例化
package main

import "fmt"

// 强制实现Door接口里面的所有方法。
var _ Door = &WoodDoor{}

type WoodDoor struct {

}

func (g *WoodDoor) Unlock() {
fmt.Println("WoodDoor unlock door。")
}

func (g *WoodDoor) Lock() {
fmt.Println("WoodDoor unlock door。")
}

func (g *WoodDoor) Open(){
fmt.Println("WoodDoor开门。")
}
func (g *WoodDoor) Close(){
fmt.Println("WoodDoor关门。")
}

11.面向接口编程
- 面向接口编程是指在开发应用时,将执行细节和执行框架进行剥离,重点关注在定义模块、组件之间的交互、协助之上的接口定义与开发。

二.面向接口编程之-实战体脂计算器

(一).要求

1
2
3
1.体脂计算器可以接受终端录入。
2.体脂计算器可以接受从文件批量读取。
3.体脂计算器可以接受从身高体重测量器上读取。