這裡的接口,可不是說那種插槽的那種接口,互相懟到一塊就完事了。
在各種語言中,提到接口,通常指的之一種規範,然後具體物件來實現這個規範的細節。
<br>
本文所使用的介面主要是約束接口,還有一種儲存介面。
註:
#在Go中,介面(interface)是一種類型,一種抽象型,它只有方法,沒有屬性##。
<br>
我們在講結構體時,Go語言基礎之結構體(春日篇)、Go語言基礎之結構體(夏日篇) 、Go語言基礎之結構體(秋日篇),提到繼承這個概念,Go是透過結構體來完成繼承的。
<br>
//车 type Car struct { Brand string //车品牌 CarNum string //车牌号 Tyre int //轮胎个数 } //给车绑定一个方法,说明车的基本信息 func (this *Car) carInfo() { fmt.Printf("品牌:%s,车牌号:%s,轮胎个数:%d\n", this.Brand, this.CarNum, this.Tyre) }
車結構體有四個屬性,同時還有一個顯示車子(carInfo)資訊的方法。 <br>
<br>
//宝马车 type BMWCar struct { //*Car和Car基本没有区别,一个存的是整个结构体,一个存的是结构体地址,用法大同小异 *Car //这就表示继承了Car这个结构体 }
//比亚迪车 type BYDCar struct { *Car }<br>比亞迪車
func main() { //一个宝马对象 var bmw1 = BMWCar{&Car{ Brand: "宝马x8", CarNum: "京666", Tyre: 4, } } //一个比亚迪对象 var byd1 = BYDCar{&Car{ Brand: "比亚迪L3", CarNum: "京111", Tyre: 4, } } //因为 BMWCar 和 BYDCar 都继承了Car,所以都有carInfo这个方法 bmw1.carInfo() byd1.carInfo() }<br>main程式碼
##
type Car interface { //车会跑 Run(speed int) //车需要加油 Refuel(oil int) //车需要转弯 Wheel(direction string) }#####執行結果##################
通过回顾,我们可以发现,车,应该作为一个基本的概念。<br>
上述Car
结构体似乎显示了车的属性,其实是不太对的。
车就是一个抽象的概念,电瓶车是车,小轿车也是车,大卡车也是车。
这些车至少有一个统一的功能,那就是跑,但是像几个轮胎了,什么品牌了。
应该是属于自己的,不再是属于Car
这个抽象的概念中了,所以,这时候用接口会更好。
<br>
type Car interface { //车会跑 Run(speed int) //车需要加油 Refuel(oil int) //车需要转弯 Wheel(direction string) }
假设车,至少有这三个动作,不管任何结构体,只要实现了Car
里面的所有方法,就代表它一定是一个车。<br>
<br>
//宝马车 type BMWCar struct { Owner string //车主 Brand string //车品牌 CarNum string //车牌号 } //构造方法 func NewBMWCar(owner string, brand string, carNum string) *BMWCar { return &BMWCar{Owner: owner, Brand: brand, CarNum: carNum} } func (this *BMWCar) Run(speed int) { fmt.Printf("我是 %s,我的车是 %s,我车牌号为 %s,我正在以 %d 速度行驶\n", this.Owner, this.Brand, this.CarNum, speed) } func (this *BMWCar) Refuel(oil int) { fmt.Printf("老板,加%d升油\n", oil) } func (this *BMWCar) Wheel(direction string) { fmt.Printf("我正在%s转弯\n", direction) }
<br>
//电瓶车 type Electromobile struct { Owner string //车主 Brand string //车品牌 } func NewElectromobile(owner string, brand string) *Electromobile { return &Electromobile{Owner: owner, Brand: brand} } func (this *Electromobile) Run(speed int) { fmt.Printf("我是 %s,我的车是 %s,我正在以 %d 速度行驶\n", this.Owner, this.Brand,, speed) } func (this *Electromobile) Refuel(oil int) { fmt.Printf("你妹的,你电动车加啥油...\n") } func (this *Electromobile) Wheel(direction string) { fmt.Printf("我正在%s转弯\n", direction) }
这里是有区别的,电瓶车没有属性CarNum
,但是仍然实现了Car
接口的所有方法,所以电瓶车在代码上,仍然是车。
func main() { var 张三的车 Car 张三的车 = NewBMWCar("张三", "宝马6", "京666") 张三的车.Run(80) 张三的车.Refuel(20) 张三的车.Wheel("左") var 李四的车 Car 李四的车 = NewElectromobile("李四", "小刀电动车") 李四的车.Run(40) 李四的车.Refuel(0) 李四的车.Wheel("左") }
第2行代码和第8行代码,变量类型是Car
接口类型,但是在赋值时,确是其他类型。<br>
Go是强类型语言,为什么类型不一致,还可以赋值,那执行结果会出问题吗???
但是我们发现执行结果是没问题的。<br>
但是為啥變數型別不一致,還是可以進行賦值並且每報錯誤呢?
我們上述程式碼可以決定BMW和##電瓶車完全實作了Car介面裡面所有的方法。
所以可以理解為Car#就是他們的爸爸,用他們的爸爸來接收兒子,當然可以咯。
<br>
以下程式碼沒有實際意義,完全是為了文法而文法。
//跑接口 type Runer interface { Run() } // 跳接口 type Jumper interface { Jump() }
//袋鼠结构体 type Roo struct { Name string } func (this *Roo) Jump() { fmt.Println("我是袋鼠,我会跳") } func (this *Roo) Run() { fmt.Println("我是袋鼠,我会跑") }
这个结构体同时实现了两个结构,一个是Runer
,一个是Jumper
。
<br>
func main() { var runner Runer var jumper Jumper runner = &Roo{Name: "袋鼠"} jumper = &Roo{Name: "袋鼠"} runner.Run() jumper.Jump() }
Roo
既然实现了两个接口,自然两个接口都可以接收Roo
这个结构体。
<br>
接口嵌套这个有点像组合,比如有跑,跳,吃等这些操作。
例如一个动物,因该是要有这些操作的,那这个动物应该也是一个接口。
并且把这些动作都拿过来才对。
<br>
//跑接口 type Runer interface { Run() } // 跳接口 type Jumper interface { Jump() } //动物接口,继承了 跑 和 跳 type Animal interface { Runer Jumper }
//袋鼠结构体,实现了跑和跳 type Roo struct { Name string } func (this *Roo) Jump() { fmt.Println("我是袋鼠,我会跳") } func (this *Roo) Run() { fmt.Println("我是袋鼠,我会跑") }
func main() { var animal Animal animal = &Roo{Name: "袋鼠"} animal = &Roo{Name: "袋鼠"} animal.Run() animal.Jump() }
<br>
上述我們學習了Go基礎的接口,主要學習了接口和繼承的區別,一個結構體實作多個介面#,介面巢狀 。
可能不太好理解,但一定要嘗試做一下,一定要堅持!
以上是一篇文章帶你了解Go語言基礎之介面(上篇)的詳細內容。更多資訊請關注PHP中文網其他相關文章!