#### Go 接口
上一節學習了Go 的封裝和繼承, 這一節來學習一下多態, 在Go 中多態是經過接口實現的, 因此先來學習一下接口
先來學習一個案例:
package main import "fmt" // 定義一個接口 type USB interface { Start() Stop() } type Phone struct {} type Camera struct {} // Phone 實現USB 接口中的方法 func (p *Phone) Start(){ fmt.Println("phone is working") } func (p *Phone) Stop(){ fmt.Println("phone stop work") } // Camera 實現USB 接口中的方法 func (c *Camera) Start(){ fmt.Println("camera is working") } func (c *Camera) Stop(){ fmt.Println("camera stop work") } // 接收一個USB interface 調用接口中的方法 func Working(usb USB) { usb.Start() usb.Stop() } func main(){ var phone = new(Phone) var camera = new(Camera) Working(phone) Working(camera) }
---
###### 接口的概念
interface 類型能夠定義一組方法,可是這些方法不須要實現,而且interface 不能包含任何變量,當某個自定義類型須要使用接口的時候,把接口
中定義的方法實現;
基本語法:
type 接口名 interface {
方法01(參數列表) 返回值列表
方法02(參數列表) 返回值列表
...
}
方法的實現:
func (a 自定義類型) 方法01(參數列表) 返回值列表{
方法內容的具體實現
}
func (a 自定義類型) 方法02(參數列表) 返回值列表{
方法內容的具體實現
}
---
說明:
1. 接口中的***全部方法都沒有方法體***,即接口中的方法都是沒有實現的方法,體現了程序設計的多態思想;
2. Go 中的接口***不須要顯示的實現***,只要一個自定義類型實現了接口類型中的全部方法,那麼這個自定義變量
就實現了這個接口;
3. 接口自己不能建立實例,可是能夠指向一個實現了該接口的自定義類型的變量;
4. 一個自定義類型只有將接口中的全部方法都實現了才能稱之爲實現了該接口;
5. 一個自定義類型只有實現了某個接口,才能將該自定義類型的變量賦給接口類型;
6. 自定義類型不侷限於結構體, 能夠是任意的自定義的數據類型;
7. 一個自定義類型能夠實現多個接口;
8. 接口中不能有任何變量;
9. 接口類型是指針類型(也可稱爲引用類型);
10. 空接口沒有任何方法***全部的類型都實現了空接口***,因此能夠把任何一個變量均可以賦值給空接口;
11. 一個接口(A)能夠繼承其它的接口(B,C...),若是要實現A接口, 須要將它繼承的接口(B,C...)也所有實現;
package main import "fmt" type Personer interface { // 1. 接口中全部的方法都沒有方法體 // 8. 接口中不能有變量 // Name string Eat() Speak() } type Animaler interface { Walk() } // 接口繼承其它接口 type Childer interface { Personer Cry() } // 父結構體 type Person struct { Name string } // 繼承Person type Student struct { Person } // 繼承Person type Teacher struct { Person } // 繼承Person type Child struct { Person } // 自定義數據類型,至關於給string 類型定義一個別名 type MyData string // Student 實現接口中的方法 func (s *Student) Eat(){ fmt.Printf("[Student] %s is eatting \n",s.Name) } func (s *Student) Speak(){ fmt.Printf("[Student] %s is speaking \n",s.Name) } // Teacher 實現接口中的方法之一 // 只有實現了接口中的全部方法才能稱爲實現了該接口 func (t *Teacher) Eat(){ fmt.Printf("[Teacher] %s is eatting \n",t.Name) } // MyData 實現接口中的方法 func (m *MyData) Eat(){ fmt.Printf("[MyData] is eatting \n") } func (m *MyData) Speak(){ fmt.Printf("[MyData] is speaking \n") } // 7. MyData 實現多個接口 func (m *MyData) Walk(){ fmt.Printf("[MyData] is walking \n") } // 11. 若是要實現Childer 接口必需要實現Personer中的方法 func (c *Child) Eat(){ fmt.Printf("[Child] %s is eatting \n",c.Name) } func (c *Child) Speak(){ fmt.Printf("[Child] %s is speaking \n",c.Name) } func (c *Child) Cry(){ fmt.Printf("[Child] %s is crying \n",c.Name) } func main(){ var p Personer var s = new(Student) // 3. 接口類型自己不能建立實例 // p.Eat() // 也就是說在沒有給接口賦值前不能直接經過接口調用接口中的方法 // 2. 只要實現了接口類型中全部的方法,就能夠賦值給接口類型 p = s p.Eat() // 4/5. 錯誤, 只有實現了接口中全部的方法才能賦值給接口類型 //var t = new(Teacher) //p = t // 6. 自定義數據類型不侷限於結構體 var m = new(MyData) p = m p.Eat() //9. 接口是指針類型 var p2 Personer fmt.Printf("%T\n",p2) // 默認值爲nil //10. 能夠把任何變量賦值給空接口 var a interface{} var b = "hello,world" a = b fmt.Println(a) // 11. var c Childer var child = new(Child) c = child c.Cry() c.Eat() }
接口實際應用的小例子:
package main import ( "fmt" "sort" ) // 自定義類型實現sort.Interface 接口 type MySort []string func (m MySort) Len() int { return len(m)} func (m MySort) Swap(i,j int) {m[i],m[j] = m[j],m[i]} func (m MySort) Less(i,j int) bool { // 先比較年 i_year := m[i][6:] j_year := m[j][6:] if i_year < j_year { return true } else if i_year > j_year { return false } else { // 再比較月 i_mon := m[i][3:5] j_mon := m[j][3:5] if i_mon < j_mon { return true } else if i_mon > j_mon { return false } else { // 比較日期 if m[i][:2] < m[j][:2] { return true } else if m[i][:2] > m[j][:2] { return false } else { return true } } } } func main(){ var strSlice = []string{ // 月/日/年 "08/01/2018", "05/01/2019", "22/06/2018", "08/02/2019", "22/12/2018", } // 排序前 fmt.Println(strSlice) // 調用sort 包排序 // 排序後的結果與預想中並不同 sort.Strings(strSlice) fmt.Println(strSlice) // 自定義類型實現sort.Interface 中的方法,實現自定義排序 sort.Sort(MySort(strSlice)) fmt.Println(strSlice) }
我的微信公衆號上有最新文章, 歡迎關注一同交流學習微信