接口的引入
【1】代碼入門:
package main
import "fmt"
//接口的定義:定義規則、定義規範,定義某種能力:
type SayHello interface{
sayHello()
}
//接口的實作:定義一個結構體:
//中國人:
type Chinese struct{
}
//實作接口的方法---》具體的實作:
func (person Chinese) sayHello(){
fmt.Println("你好")
}
//接口的實作:定義一個結構體:
//美國人:
type American struct{
}
//實作接口的方法---》具體的實作:
func (person American) sayHello() {
fmt.Println("hi")
}
//定義一個函數:專門用來各國人打招呼的函數,接收具備SayHello接口的能力的變量:
func greet(s SayHello) {
s.sayHello()
}
func main(){
c := Chinese{}
a := American{}
greet(c)
greet(a)
}
【2】總結:
(1)接口中可以定義一組方法,但不需要實作,不需要方法體。并且接口中不能包含任何變量。到某個自定義類型要使用的時候(實作接口的時候),再根據具體情況把這些方法具體實作出來。
(2)實作接口要實作所有的方法才是實作。
(3)Golang中的接口不需要顯式的實作接口。Golang中沒有implement關鍵字。
(Golang中實作接口是基于方法的,不是基于接口的)
例如:
A接口 a,b方法
B接口 a,b方法
C結構體 實作了 a,b方法 ,那麼C實作了A接口,也可以說實作了B接口 (隻要實作全部方法即可,和實際接口耦合性很低,比Java松散得多)
(4)接口目的是為了定義規範,具體由别人來實作即可。
接口注意事項
【1】接口本身不能建立執行個體,但是可以指向一個實作了該接口的自定義類型的變量。
// 直接用接口建立執行個體,出錯:
// var s SayHello
// s.sayHello()
【2】隻要是自定義資料類型,就可以實作接口,不僅僅是結構體類型。
type integer int
func (i integer) sayHello() {
fmt.Println("say hi + ",i)
}
func main(){
var i integer = 10
s = i
s.sayHello()
}
【3】一個自定義類型可以實作多個接口
package main
import "fmt"
type AInterface interface{
a()
}
type BInterface interface{
b()
}
type Stu struct{
}
func (s Stu) a() {
fmt.Println("this is a()")
}
func (s Stu) b() {
fmt.Println("this is b()")
}
func main() {
var s Stu;
var a AInterface = s
var b BInterface = s
a.a()
b.b()
}
【4】一個接口(比如A接口)可以繼承多個别的接口(比如B,C接口),這時如果要實作A接口,也必須将B,C接口的方法也全部實作。
package main
import "fmt"
type CInterface interface{
c()
}
type BInterface interface{
b()
}
type AInterface interface{
CInterface
BInterface
a()
}
type Stu struct{
}
func (s Stu) a() {
fmt.Println("a")
}
func (s Stu) b() {
fmt.Println("b")
}
func (s Stu) c() {
fmt.Println("c")
}
func main() {
var s Stu
var a AInterface = s
a.a()
a.b()
a.c()
}
【5】interface類型預設是一個指針(引用類型),如果沒有對interface初始化就使用,那麼會輸出nil
【6】空接口沒有任何方法,是以可以了解為所有類型都實作了空接口,也可以了解為我們可以把任何一個變量賦給空接口。
type E interface {
}
func main() {
var e E = s
fmt.Println(e)
var e2 interface{} = s
fmt.Println(e2)
var num float32 = 9.99
var e3 interface{} = num
fmt.Println(e3)
}
多态
【1】基本介紹
變量(執行個體)具有多種形态。面向對象的第三大特征,在Go語言,多态特征是通過接口實作的。可以按照統一的接口來調用不同的實作。這時接口變量就呈現不同的形态。
【2】案例:
//定義一個函數:專門用來各國人打招呼的函數,接收具備SayHello接口的能力的變量:
func greet(s SayHello) {
s.sayHello()
}
【3】接口展現多态特征
1) 多态參數: s叫多态參數
2) 多态數組 :
比如:定義SayHello數組,存放中國人結構體、美國人結構體
var arr [3]SayHello
arr[0] = American{"Rose"}
arr[1] = Chinese{"菜園子"}
arr[2] = Chinese{"蜘蛛俠"}
fmt.Println(arr)
斷言
【1】什麼是斷言?
Go語言裡面有一個文法,可以直接判斷是否是該類型的變量: value, ok := element.(T),這裡value就是變量的值,ok是一個bool類型,element是interface變量,T是斷言的類型。
【2】斷言的案例引入:
package main
import "fmt"
type SayHello interface{
sayHello()
}
type Chinese struct{
name string
}
func (person Chinese) sayHello(){
fmt.Println("你好")
}
func (person Chinese) niuYangGe(){
fmt.Println("扭秧歌")
}
type American struct{
name string
}
func (person American) sayHello(){
fmt.Println("hi")
}
//定義一個函數:專門用來各國人打招呼的函數,接收具備SayHello接口的能力的變量:
func greet(s SayHello) {
s.sayHello()
//斷言:
//看s是否能轉成Chinese類型并且賦給ch變量,flag是判斷是否轉成功
var ch Chinese = s.(Chinese)
ch.niuYangGe()
fmt.Println("打招呼")
}
func main() {
c := Chinese{}
greet(c)
// a := American{}
// greet(a)
}
解決第二個傳回值問題:
//定義一個函數:專門用來各國人打招呼的函數,接收具備SayHello接口的能力的變量:
func greet(s SayHello) {
s.sayHello()
//斷言:
//看s是否能轉成Chinese類型并且賦給ch變量,flag是判斷是否轉成功
// var ch Chinese = s.(Chinese)
// ch.niuYangGe()
ch,flag := s.(Chinese)
if flag == true {
ch.niuYangGe()
} else {
fmt.Println("美國人不會扭秧歌")
}
fmt.Println("打招呼")
}
【3】Type Switch 的基本用法
Type Switch 是 Go 語言中一種特殊的 switch 語句,它比較的是類型而不是具體的值。它判斷某個接口變量的類型,然後根據具體類型再做相應處理。
func (person American) disco() {
fmt.Println("野狼disco")
}
//定義一個函數:專門用來各國人打招呼的函數,接收具備SayHello接口的能力的變量:
func greet(s SayHello) {
s.sayHello()
//斷言:
//看s是否能轉成Chinese類型并且賦給ch變量,flag是判斷是否轉成功
// var ch Chinese = s.(Chinese)
// ch.niuYangGe()
// ch,flag := s.(Chinese)
// if flag == true {
// ch.niuYangGe()
// } else {
// fmt.Println("美國人不會扭秧歌")
// }
switch s.(type) {
case Chinese:
ch := s.(Chinese)
ch.niuYangGe()
case American:
am := s.(American)
am.disco()
}
fmt.Println("打招呼")
}
源碼位址:「連結」
參考個人部落格平台:cyz