首頁 > 軟體

go語言interface介面繼承多型範例及定義解析

2022-04-15 13:01:04

1.什麼是介面

介面就是一種規範與標準,在生活中經常見介面,例如:筆記型電腦的USB介面,可以將任何廠商生產的滑鼠與鍵盤,與電腦進行連結。為什麼呢?原因就是,USB介面將規範和標準制定好後,各個生產廠商可以按照該標準生產滑鼠和鍵盤就可以了。

在程式開發中,介面只是規定了要做哪些事情,幹什麼。具體怎麼做,介面是不管的。這和生活中介面的案例也很相似,例如:USB介面,只是規定了標準,但是不關心具體滑鼠與鍵盤是怎樣按照標準生產的.

在企業開發中,如果一個專案比較龐大,那麼就需要一個能理清所有業務的架構師來定義一些主要的介面,這些介面告訴開發人員你需要實現那些功能。

2.介面定義

介面定義的語法如下:

方式一:interface接收任意資料格式
//先定義介面  一般以er結尾  根據介面實現功能
type CurrencyEr2 interface{
	Symbol() string
}

方式二:指定型別
type Currency string

怎樣具體實現介面中定義的方法呢?

func (c Currency)Symbol() string {
	m := ""
	switch c {
	case "CNY":
		// 人民幣
		m = "¥"
	case "KRW":
		// 韓幣
		m = "₩"
	case "TWD":
		// 臺幣
		m = "$"
	case "JPY":
		// 日元
		m = "¥"
	case "USD":
		// 美元
		m = "$"
	}
	return m
}

具體的呼叫如下:

func main() {
  // 方式一:
  a:=CurrencyEr2(Currency("CNY")).Symbol()
	fmt.Println(a)
  // 方式二:
	b:=Currency("CNY").Symbol()
	fmt.Println(b)
}

只要類(結構體)實現對應的介面,那麼根據該類建立的物件,可以賦值給對應的介面型別。

介面的命名習慣以er結尾。

3.多型

介面有什麼好處呢?實現多型。

多型就是同一個介面,使用不同的範例而執行不同操作

所謂多型指的是多種表現形式,如下圖所示:

使用介面實現多型的方式如下:

package main
import "fmt"
//先定義介面  一般以er結尾  根據介面實現功能
type CurrencyEr2 interface {
	//方法  方法的宣告
	Symbol() string
}
type Currency string
type Currency2 string
func (c Currency) Symbol() string {
	m := ""
	switch c {
	case "CNY":
		m = "¥"
	}
	return m
}
func (c Currency2) Symbol() string {
	m := ""
	switch c {
	case "USD":
		m = "$"
	}
	return m
}
//多型的實現
//將介面作為函數引數  實現多型
func Start(c CurrencyEr2) string {
	return c.Symbol()
}
func main() {
	//呼叫多型函數
	a := Start(Currency("CNY"))
	fmt.Println(a)
	//呼叫多型函數
	b := Start(Currency2("USD"))
	fmt.Println(b)
}

多型加減計算器

package main
import "fmt"
//定義介面
type Opter interface {
	//方法宣告
	Result() int
}
//父類別結構體
type Operate struct {
	num1 int
	num2 int
}
//加法子類結構體
type Add struct {
	Operate
}
//實現加法子類的方法
func (a *Add) Result() int {
	return a.num1 + a.num2
}
//減法子類結構體
type Sub struct {
	Operate
}
//實現減法子類的方法
func (s *Sub) Result() int {
	return s.num1 - s.num2
}
//建立一個類負責物件建立
//工廠類
type Factory struct {
}
func (f *Factory) Result(num1 int, num2 int, ch string) int {
	sum := 0
	switch ch {
	case "+":
		var a Add
		a.num1 = num1
		a.num2 = num2
		sum = Opter.Result(&a)
	case "-":
		var s Sub
		s.num1 = num1
		s.num2 = num2
		sum = Opter.Result(&s)
	}
	return sum
}
//通過設計模式呼叫
func main() {
	//建立工廠物件
	var f Factory
	a:= f.Result(10, 20, "+")
	fmt.Println(a)
}

4.介面繼承與轉換

介面也可以實現繼承:

package main
import "fmt"
//先定義介面  一般以er結尾  根據介面實現功能
type Humaner2 interface {   //子集
    //方法  方法的宣告
    sayhi()
}
type Personer interface {  //超集
    Humaner2   //繼承sayhi()

    sing(string)
}
type student13 struct {
    name  string
    age   int
    score int
}
func (s *student13)sayhi()  {
    fmt.Printf("大家好,我是%s,今年%d歲,我的成績%d分n",s.name,s.age,s.score)
}
func (s *student13)sing(name string)  {
    fmt.Println("我為大家唱首歌",name)
}
func main() {
    //介面型別變數定義
    var h Humaner2
    var stu student13 = student13{"小吳",18,59}
    h = &stu
    h.sayhi()
    //介面型別變數定義
    var p Personer
    p = &stu
    p.sayhi()
    p.sing("大碗麵")
}

介面繼承後,可以實現“超集”介面轉換“子集”介面,程式碼如下:

package main
import "fmt"
//先定義介面  一般以er結尾  根據介面實現功能
type Humaner2 interface {   //子集
    //方法  方法的宣告
    sayhi()
}
type Personer interface {  //超集
    Humaner2   //繼承sayhi()
    sing(string)
}
type student13 struct {
    name  string
    age   int
    score int
}
func (s *student13)sayhi()  {
    fmt.Printf("大家好,我是%s,今年%d歲,我的成績%d分n",s.name,s.age,s.score)
}
func (s *student13)sing(name string)  {
    fmt.Println("我為大家唱首歌",name)
}
func main()  {
    //介面型別變數定義
    var h Humaner2  //子集
    var p Personer    //超集
    var stu student13 = student13{"小吳",18,59}
    p = &stu
    //將一個介面賦值給另一個介面
    //超集中包含所有子集的方法
    h = p  //ok
    h.sayhi()
    //子集不包含超集
    //不能將子集賦值給超集
    //p = h  //err
    //p.sayhi()
    //p.sing("大碗麵")
}

5.空介面

空介面(interface{})不包含任何的方法,正因為如此,所有的型別都實現了空介面,因此空介面可以儲存任意型別的數值。

例如:

var i interface{}
//介面型別可以接收任意型別的資料
//fmt.Println(i)
fmt.Printf("%Tn",i)
i = 10
fmt.Println(i)
fmt.Printf("%Tn",i)

當函數可以接受任意的物件範例時,我們會將其宣告為interface{},最典型的例子是標準庫fmt中PrintXXX系列的函數,例如:

func Printf(fmt string, args ...interface{})
func Println(args ...interface{})

如果自己定義函數,可以如下:

func Test(arg ...interface{}) {
}

Test( )函數可以接收任意個數,任意型別的引數。

6.介面轉換

結論:超集可以轉換為子集,子集不可以轉換為超集

package main
import "fmt"
type Humaner interface { //子集
	sayhi()
}
type Personer interface { //超集
	Humaner //匿名欄位,繼承了sayhi()
	sing(lrc string)
}
type Student struct {
	name string
	id   int
}
//Student實現了sayhi()
func (tmp *Student) sayhi() {
	fmt.Printf("Student[%s, %d] sayhin", tmp.name, tmp.id)
}
func (tmp *Student) sing(lrc string) {
	fmt.Println("Student在唱著:", lrc)
}
func main() {
	//超集可以轉換為子集,反過來不可以
	var iPro Personer //超集
	iPro = &Student{"mike", 666}
	var i Humaner //子集
	//iPro = i //err
	i = iPro //可以,超集可以轉換為子集
	i.sayhi()
}

7.實現map字典介面

package main
import (
	"fmt"
	"sync"
)
type UserAges struct {
	ages map[string] int
	sync.Mutex
}
func (u *UserAges)Add(name string,age int)  {
	u.Lock()
	defer u.Unlock()
	u.ages[name] = age
}
func (u *UserAges)Get(name string)int{
	if age,ok:=u.ages[name];ok{
		return age
	}
	return -1
}
func main() {
	dic:=make(map[string]int)
	dic["age"] = 18
	r:=UserAges{ages: dic}
	r.Add("jeff",20)
	fmt.Println(r)
	age:=r.Get("age")
	fmt.Println(age)
}

8.interface案例

package main
import "fmt"
type Bike interface {
	save()
	update()
	insert()
}
type User struct {
	name string
}
func (this *User) save() {
	fmt.Println("儲存成功", this.name)
}
func (this *User) update() {
	fmt.Println("更新成功", this.name)
}
func (this *User) insert() {
	fmt.Println("插入成功", this.name)
}
func main() {
	var data Bike = &User{name: "jeff"}
	data.save()
	data.update()
	data.insert()
}

以上就是go語言interface介面繼承多型範例及定義解析的詳細內容,更多關於go語言interface介面繼承多型的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com