Golang的封裝繼承與多態


類的封裝及方法綁定

  • Golang支持類的操作,但是沒有class關鍵字,使用struct類模擬類
  • 在struct中定義函數需要在外部綁定,通過在方法前面指定數據類型類綁定方法到指定類,有點類似於C#的擴展函數
package main

import "fmt"

// C++ 創建類的方式
/*
	class Person{
		public:
			string name
			int age

		public:
			Sayhi(){
				...
			}
	}
*/

// Golang創建一個person類,綁定Sayhi()方法
type Person struct {
	Name string
	Age int
}

// 在類外面綁定方法
// 通過在方法前面指定數據類型類綁定方法到指定類,有點類似於C#的擴展函數
// 下面這個Person數據類型,是Person對象的一個拷貝,在該函數下修改person里面的成員值,原始數據類型值不會改變
// 如果想在綁定的函數中可以修改原始數據類型的值,可以通過指針func (person *Person) Sayhi(){}的方式來定義
func (person Person) Sayhi(){
	// 類的方法,使用自己的成員Name
	fmt.Println("hi, my name is ",person.Name)
}

// 通過指針的方式將函數綁定在指定類中,在該函數下可以修改原始數據類型的成員值
func (this *Person) SayHello(){
	this.Name = "china"
	fmt.Println("hi, my name is ",this.Name)
}

func main() {
	person := Person{
		Name: "simple",
		Age: 25,
	}
	fmt.Println(person)
	person.Sayhi()

	fmt.Println(person)
	person.SayHello()
}

image

類的繼承

  • 當我們在一個類中,直接包含另外一個類的類型,並且沒寫字段名的時候。它默認就是對另一個類的繼承
  • 繼承的時候,雖然沒有定義字段名稱,但是會自動創建一個默認的同名字段,這是為了在子類中,依然可以操作父類,因為子類父類可能出現同名的字段
package main

import "fmt"

// 定義一個人類
type Human struct {
	Name   string
	Age    int
	Gender int
}

// 給人類綁定一個打招呼的方法
func (this *Human) Sayhi() {
	fmt.Println("hello, my name is ", this.Name, "age is ", this.Age)
}

// 定義一個學生
// 在其他類中引用指定類
type Student struct {
	hum    Human		// 類的嵌套
	School string
}

// 定義一個老師,來繼承Human
type Teacher struct {
	Human					// 當我們在一個類中,直接包含另外一個類的類型,並且沒寫字段名的時候。它默認就是對另一個類的繼承
	Subject string

}

func main() {
	// 在學習類的繼承之前,我們先來看一下類的嵌套
	strudent := Student{hum: Human{
		Name:   "Simple",
		Age:    24,
		Gender: 1,
	},
		School: "成都七中",
	}
	fmt.Println(strudent)

	// 繼承類
	teacher := Teacher{}
	teacher.Name = "陳老師"
	teacher.Age = 30
	teacher.Subject = "計算機"
	fmt.Println(teacher)
	teacher.Sayhi()				// 同時綁定的方法也繼承下來了

	// 繼承的時候,雖然沒有定義字段名稱,但是會自動創建一個默認的同名字段
	// 這是為了在子類中,依然可以操作父類,因為子類父類可能出現同名的字段
	teacher.Human.Name = "林老師"
	fmt.Println(teacher)
	teacher.Sayhi()				// 同時綁定的方法也繼承下來了
}

image

類的訪問權限(訪問修飾符)

  • 在Golang中,權限都是通過首字母大小寫來標識的
  • import -> 如果包名不同,只有大寫字母開頭的才能訪問
  • 對於類里面的成員、方法 -> 只有首字母大寫才能在其他包中使用

多態(通過interface實現)

接口的使用

  • 在C++中,實現接口的時候,使用純虛函數代替接口
  • 在Golang中,有專門的關鍵字interface來代表接口
  • interface不僅僅是用於處理多態的,它可以接收任意的數據類型,類似於void
package main

import "fmt"

// 在C++中,實現接口的時候,使用純虛函數代替接口
// 在Golang中,有專門的關鍵字interface來代表接口
// interface不僅僅是用於處理多態的,它可以接收任意的數據類型,類似於void
func main() {
	var i, j, k interface{}
	names := []string{"simple", "china"}

	i = names
	fmt.Println("i代表切片數組:", i)

	age := 24
	j = age
	fmt.Println("j代表數字:", j)

	str := "hello world"
	k = str
	fmt.Println("k代表字符串:", k)

	// 上上面的代碼中,我們現在只知道k是interface,但是不能夠明確知道它代表的數據類型
	// 通過變量.(數據類型)判斷指定interface是否為指定的數據類型
	kval, ok := k.(int)
	if !ok {
		fmt.Println("k不是int")
	} else {
		fmt.Println("k是int,值為:", kval)
	}

	// 最常用的常見:把interface當初函數的參數,類似於fmt.Println函數,func Println(a ...interface{}) (n int, err error) {}
	// 可以通過switch來判斷用戶輸入的數據類型,然后根據不同的數據類型做相應的邏輯處理

	// 創建一個具有三個接口的數據切片
	array := make([]interface{}, 4)
	array[0] = 1
	array[1] = "hello world"
	array[2] = true
	array[3] = 3.1415

	for _, val := range array{
		// 獲取當前接口的真正數據類型
		switch t := val.(type) {
		case int:
			fmt.Printf("當前數據類型為int,內容為:%d\n",t)
		case string:
			fmt.Printf("當前數據類型為string,內容為:%s\n",t)
		case bool:
			fmt.Printf("當前數據類型為bool,內容為:%v\n",t)				// %v可以自動推導數據類型
		default:
			fmt.Printf("不是合理的數據類型")
		}
	}
}

image

多態

  • C語言的多態需要父子繼承關系
  • Golang的多態不需要繼承,只要實現了相同的接口即可
  • 實現Golang多態,需要定義接口
package main

import "fmt"

// 定義一個飛的行為,不同可以飛行的東西可能不一樣

// 定義一個接口,注意類型是interface
type IFly interface {
	// 接口函數可以有多個,但是只能有原型,不能有實現
	Fly()
}

// 定義一個老鷹類
type Glede struct {
	Name string
}

// 老鷹的飛行函數
func (this *Glede) Fly() {
	fmt.Println(this.Name, ":展翅翱翔")
}

type Human struct {
	Name string
}

func (this *Human) Fly() {
	fmt.Println(this.Name,":不會飛")
}

// 實現多態:定義一個多態的通用接口,傳入不同的對象,調用通向的方法,實現不同的效果
func DoFly(fly IFly)  {
	fly.Fly()
}

func main() {
	glede := Glede{Name: "老鷹"}
	glede.Fly()

	var fly IFly				// 定義一個包含Fly的接口變量
	fly = &glede				// 對fly賦值為glede,接口需要使用指針來賦值
	fly.Fly()

	human := Human{Name: "人類"}
	human.Fly()

	fly = &human
	fly.Fly()

	// 多態的實現
	fmt.Println("***多態***")
	DoFly(&glede)
	DoFly(&human)
}

image

  • 定義一個接口,里面設計好需要的接口,可以有多個
  • 任何實現了這個接口的類型,都可以賦值給這個接口,從而實現多態
  • 多個類之間不需要有繼承關系
  • 如果interface定義了多個接口,那么實現類必須實現全部函數,才可以賦值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM