您好,登錄后才能下訂單哦!
序:
在Java語(yǔ)言中,存在兩套完全獨(dú)立的類型系統(tǒng):一套是值類型系統(tǒng),主要是基本類型,如byte int boolean char double等,這些類型基于值語(yǔ)義;一套是以object類型為根的對(duì)象類型系統(tǒng),這些類型可以定義成員變量和成員方法,可以有虛函數(shù),基于引用語(yǔ)義,只允許在堆上創(chuàng)建(通過(guò)使用關(guān)鍵字new)。Java語(yǔ)言中的Any類型就是整個(gè)對(duì)象系統(tǒng)的根——java.lang.Object類型,只有對(duì)象類型系統(tǒng)中的實(shí)例才可以被Any類型引用。值類型想要被Any類型引用,需要裝箱(boxing)過(guò)程,比如int類型需要裝箱成為Integer類型。另外,只有對(duì)象類型系統(tǒng)中的類型才可以實(shí)現(xiàn)接口,具體方法是讓該類型從要實(shí)現(xiàn)的接口繼承。
相比之下,Go語(yǔ)言中的大多數(shù)類型都是值語(yǔ)義,并且都可以包含對(duì)應(yīng)的操作方法。在需要的時(shí)候,你可以給任何類型(包括內(nèi)置類型)"增加"新方法。而在實(shí)現(xiàn)某個(gè)接口時(shí),無(wú)需從該接口集成(事實(shí)上,GO語(yǔ)言根本就不支持面向?qū)ο笏枷胫械睦^承語(yǔ)法),只需要實(shí)現(xiàn)該接口要求的所有方法即可。任何類型都可以被Any類型引用。Any類型就是空接口,即interface()。
為類型添加方法:
在GO語(yǔ)言中,你可以給任意類型(包括內(nèi)置類型,但不包括指針類型)添加相應(yīng)的方法,例如:
type Integer int
func (a Integer) Less (b Integer) bool {
return a < b
}
在這個(gè)例子中,我們定義了一個(gè)新類型Integer,它和int沒(méi)有本質(zhì)不同,只是它為內(nèi)置的int類型增加了個(gè)新方法Less()。
這樣實(shí)現(xiàn)了Integer后,就可以讓整型像一個(gè)普通類一樣使用:
func main() {
var a Integer = 1
if a.Less(2) {
fmt.Println(a, "Less 2")
}
}
值語(yǔ)義和引用語(yǔ)義:
值語(yǔ)義和引用語(yǔ)義的差別在于賦值,比如下面的例子:
b = a
b.Modify()
如果b的修改不會(huì)影響a的值,那么此類型屬于值類型。如果會(huì)影響a的值,那么此類型是引用類型。
GO語(yǔ)言中大多數(shù)類型都基于值語(yǔ)義,包括:
基本類型,如byte int bool float32 float64 和 string 等
復(fù)合類型,如數(shù)組(array) 結(jié)構(gòu)體(struct) 和指針(pointer) 等
GO語(yǔ)言中類型的值語(yǔ)義表現(xiàn)的非常徹底。之所以這么說(shuō),是因?yàn)閿?shù)組。
GO語(yǔ)言中的數(shù)組和基本類型沒(méi)有區(qū)別,是很純粹的值類型,例如:
var a = [3]int{1,2,3}
var b = a
b[1]++
fmt.Println(a, b)
該程序的運(yùn)行結(jié)果如下:
[1 2 3] [1 3 3]
這表明b=a賦值語(yǔ)句是數(shù)組內(nèi)容的完整復(fù)制。要想表達(dá)引用,需要用指針:
var a = [3]int{1, 2, 3}
var b = &a
b[1]++
fmt.Println(a, *b)
該程序的運(yùn)行結(jié)果如下:
[1 3 3] [1 3 3]
這表明b=&a賦值語(yǔ)句是數(shù)組內(nèi)容的引用。變量b的類型不是[3]int,而是*[3]int類型。
GO語(yǔ)言中4個(gè)類型比較特別,看起來(lái)像引用類型,如下所示。
數(shù)組切片:指向數(shù)組(array)的一個(gè)區(qū)間。
map:極其常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),提供鍵值查詢能力。
channel:執(zhí)行體(goroutine)間的通信設(shè)施。
接口(interface):對(duì)一組滿足某個(gè)契約的類型的抽象。
但是這并不影響我們將GO語(yǔ)言類型看做值語(yǔ)義。下面我們來(lái)看看這4個(gè)類型。
數(shù)組切片本質(zhì)上是一個(gè)區(qū)間,你可以大致將[]T表示為:
type slice struct {
first *T
len int
cap int
}
因?yàn)閿?shù)組切片是指向數(shù)組的指針,所以可以改變所指向的數(shù)組元素并不奇怪。數(shù)組切片類型本身的賦值仍然是值語(yǔ)義。
結(jié)構(gòu)體:
GO語(yǔ)言的結(jié)構(gòu)體(struct)和其他語(yǔ)言的類(class)有同等的地位,但Go語(yǔ)言放棄了包括集成在內(nèi)的大量面向?qū)ο筇匦裕槐A袅私M合(composition)這個(gè)最基礎(chǔ)的特性。
上面我們說(shuō)到,所有的Go語(yǔ)言類型(指針類型除外)都可以有自己的方法。在這個(gè)背景下,Go語(yǔ)言的結(jié)構(gòu)體只是很普通的復(fù)合類型,平淡無(wú)奇。例如,我們要定義一個(gè)矩形類型:
type Rect struct {
x, y float64
width, height float64
}
然后我們定義成員方法Area()來(lái)計(jì)算矩形的面積:
func (r *Rect) Area() float64 {
return r.width * r.height
}
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。