Go語言學習 十一 物件導向程式設計 型別系統

2021-08-14 06:50:43 字數 2648 閱讀 2352

乙個典型的型別系統通常包含如下基本內容:

相比之下,go語言中的大多數型別都是值語義,並且都可以包含對應的操作方法。在需要

的時候,你可以給任何型別(包括內建型別)「增加」新方法。而在實現某個介面時,無需從

該介面繼承(事實上,go語言根本就不支援物件導向思想中的繼承語法),只需要實現該介面

要求的所有方法即可。任何型別都可以被 any 型別引用。 any型別就是空介面,即inte***ce{} 。

例如:

package main

import (

"fmt"

)//定義乙個新的型別

type integer int

func main()

}//定義方法,呼叫者為integer型別,接受integer型別,返回bool值

func (a integer) less(b integer) bool

在這個例子中,我們定義了乙個新型別 integer ,它和 int 沒有本質不同,只是它為內建的

int 型別增加了個新方法 less() 。這樣實現了integer後,就可以讓整型像乙個普通的類一樣使用了.

上面的方法的呼叫方式是 型別.方法名(引數列表),例如:

a.less(4)

這種呼叫方式就是物件導向的體現.

他和面向過程有明顯的區別,如下修改為面向過程的方法定義.

func integer_less(a,b integer)bool

呼叫方式是 方法名(引數列表),例如:

integer_less(a,2)

這有時會是個額外成本,因為物件有時很小(比如4位元組),用指標傳遞並不划算。

只有在你需要修改物件的時候,才必須用指標。它不是go語言的約束,而是一種自然約束。

舉個例子:

package main

import (

"fmt"

)//定義乙個新的型別

type integer int

func main()

//通過integer的指標呼叫

func (a *integer) add(b integer)

執行該程式,得到的結果是: a=6 。

如果你實現成員方法時的呼叫者不是a的指標而是值(即傳入integer,而非 *integer)

如下所示

func (a integer) add(b integer)
那麼執行程式得到的結果是a=3

也就是維持原來的值,這點需要特別注意.

究其原因,是因為go語言和c語言一樣,型別都是基於值傳遞的。要想修改變數的值,只能

傳遞指標。

值語義和引用語義的差別在於賦值

如果b的修改不會影響a的值,那麼此型別屬於值型別。如果會影響a的值,那麼此型別是引用型別。

go語言中的大多數型別都基於值語義,包括:

var a = [3]int

var b = a

b[1]++

fmt.println(a, b)

該程式的執行結果如下:

[1 2 3] [1 3 3]。

這表明 b=a 賦值語句是陣列內容的完整複製。要想表達引用,需要用指標:

var a = [3]int

var b = &a

b[1]++

fmt.println(a, *b)

該程式的執行結果如下:

[1 3 3] [1 3 3]

這表明 b=&a 賦值語句是陣列內容的引用。變數 b 的型別不是 [3]int ,而是 *[3]int 型別。

go語言中有4個型別比較特別,看起來像引用型別,如下所示。

1.陣列切片:指向陣列(array)的乙個區間。

2.map:極其常見的資料結構,提供鍵值查詢能力。

3.channel:執行體(goroutine)間的通訊設施。

4.介面(inte***ce):對一組滿足某個契約的型別的抽象。

但是這並不影響我們將go語言型別看做值語義。

陣列切片本質上是乙個區間,你可以大致將 t 表示為:

type slice struct
因為陣列切片內部是指向陣列的指標,所以可以改變所指向的陣列元素並不奇怪。陣列切片

型別本身的賦值仍然是值語義

go語言的結構體(struct)和其他語言的類(class)有同等的地位,但go語言放棄了包括繼

承在內的大量物件導向特性,只保留了組合(composition)這個最基礎的特性。

組合甚至不能算物件導向特性,因為在c語言這樣的過程式程式語言中,也有結構體,也有

組合。組合只是形成復合型別的基礎。

上面我們說到,所有的go語言型別(指標型別除外)都可以有自己的方法。在這個背景下,

go語言的結構體只是很普通的復合型別,平淡無奇。例如,我們要定義乙個矩形型別:

type rect struct 

//然後我們定義成員方法 area() 來計算矩形的面積:

func (r *rect) area() float64

可以看出go語言中結構體的使用方式與c語言並沒有明顯不同。

Go語言學習 十三 物件導向程式設計 繼承

go語言也提供了繼承,但是採用了組合的方式,所以我們將其稱為匿名組合 package main import fmt 定義基類 type base struct 基類相關的2個成員方法 func base base a func base base b 定義子類 type son struct 重寫...

Go語言學習 十三 物件導向程式設計 繼承

package main import fmt 定義基類 type base struct 基類相關的2個成員方法 func base base a func base base b 定義子類 type son struct 重寫基類的b方法 func son son b func main son...

Go語言學習十一 go語言切片

go 語言切片是對陣列的抽象。go 陣列的長度不可改變,在特定場景中這樣的集合就不太適用,go中提供了一種靈活,功能強悍的內建型別切片 動態陣列 與陣列相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。你可以宣告乙個未指定大小的陣列來定義切片 var identifier typ...