Fixes #198
This commit is contained in:
chai2010
2016-01-18 11:22:04 +08:00
parent 884ada9cd0
commit 9666211cd7
71 changed files with 107 additions and 105 deletions

View File

@@ -77,7 +77,7 @@ fmt.Println(perim.Distance()) // "12"
在上面兩個對Distance名字的方法的調用中編譯器會根據方法的名字以及接收器來決定具體調用的是哪一個函數。第一個例子中path[i-1]數組中的類型是Point因此Point.Distance這個方法被調用在第二個例子中perim的類型是Path因此Distance調用的是Path.Distance。
對於一個給定的類型,其內部的方法都必有唯一的方法名但是不同的類型卻可以有同樣的方法名比如我們這里Point和Path就都有Distance這個名字的方法所以我們沒有必要非在方法名之前加類型名來消除歧義比如PathDistance。這里我們已經看到了方法比之函數的一些好處方法名可以簡短。當我們在包外調用的時候這種好處就會被放大因爲我們可以使用這個短名字而可以省略掉包的名字下面是例子
對於一個給定的類型,其內部的方法都必有唯一的方法名但是不同的類型卻可以有同樣的方法名比如我們這里Point和Path就都有Distance這個名字的方法所以我們沒有必要非在方法名之前加類型名來消除歧義比如PathDistance。這里我們已經看到了方法比之函數的一些好處方法名可以簡短。當我們在包外調用的時候這種好處就會被放大因爲我們可以使用這個短名字而可以省略掉包的名字下面是例子
```Go
import "gopl.io/ch6/geometry"

View File

@@ -9,9 +9,9 @@ func (p *Point) ScaleBy(factor float64) {
}
```
這個方法的名字是`(*Point).ScaleBy`。這里的括號是必的;沒有括號的話這個表達式可能會被理解爲`*(Point.ScaleBy)`
這個方法的名字是`(*Point).ScaleBy`。這里的括號是必的;沒有括號的話這個表達式可能會被理解爲`*(Point.ScaleBy)`
在現實的程序里一般會約定如果Point這個類有一個指針作爲接收器的方法那麽所有Point的方法都必有一個指針接收器,卽使是那些併不需要這個指針接收器的函數。我們在這里打破了這個約定隻是爲了展示一下兩種方法的異同而已。
在現實的程序里一般會約定如果Point這個類有一個指針作爲接收器的方法那麽所有Point的方法都必有一個指針接收器,卽使是那些併不需要這個指針接收器的函數。我們在這里打破了這個約定隻是爲了展示一下兩種方法的異同而已。
隻有類型(Point)和指向他們的指針(*Point),才是可能會出現在接收器聲明里的兩種接收器。此外,爲了避免歧義,在聲明方法時,如果一個類型名本身是一個指針的話,是不允許其出現在接收器中的,比如下面這個例子:

View File

@@ -37,7 +37,7 @@ fmt.Println(p.Distance(q.Point)) // "10"
Point類的方法也被引入了ColoredPoint。用這種方式內嵌可以使我們定義字段特别多的複雜類型我們可以將字段先按小類型分組然後定義小類型的方法之後再把它們組合起來。
讀者如果對基於類來實現面向對象的語言比較熟悉的話可能會傾向於將Point看作一個基類而ColoredPoint看作其子類或者繼承類或者將ColoredPoint看作"is a" Point類型。但這是錯誤的理解。請註意上面例子中對Distance方法的調用。Distance有一個參數是Point類型但q併不是一個Point類所以盡管q有着Point這個內嵌類型我們也必要顯式地選擇它。嚐試直接傳q的話你會看到下面這樣的錯誤
讀者如果對基於類來實現面向對象的語言比較熟悉的話可能會傾向於將Point看作一個基類而ColoredPoint看作其子類或者繼承類或者將ColoredPoint看作"is a" Point類型。但這是錯誤的理解。請註意上面例子中對Distance方法的調用。Distance有一個參數是Point類型但q併不是一個Point類所以盡管q有着Point這個內嵌類型我們也必要顯式地選擇它。嚐試直接傳q的話你會看到下面這樣的錯誤
```go
p.Distance(q) // compile error: cannot use q (ColoredPoint) as Point

View File

@@ -34,7 +34,7 @@ time.AfterFunc(10 * time.Second, r.Launch)
譯註:省掉了上面那個例子里的匿名函數。
和方法"值"相關的還有方法表達式。當調用一個方法時,與調用一個普通的函數相比,我們必要用選擇器(p.Distance)語法來指定方法的接收器。
和方法"值"相關的還有方法表達式。當調用一個方法時,與調用一個普通的函數相比,我們必要用選擇器(p.Distance)語法來指定方法的接收器。
當T是一個類型時方法表達式可能會寫作T.f或者(*T).f會返迴一個函數"值",這種函數會將其第一個參數用作接收器,所以可以用通常(譯註:不寫選擇器)的方式來對其進行調用:

View File

@@ -2,7 +2,7 @@
一個對象的變量或者方法如果對調用方是不可見的話,一般就被定義爲“封裝”。封裝有時候也被叫做信息隱藏,同時也是面向對象編程最關鍵的一個方面。
Go語言隻有一種控製可見性的手段大寫首字母的標識符會從定義它們的包中被導出小寫字母的則不會。這種限製包內成員的方式同樣適用於struct或者一個類型的方法。因而如果我們想要封裝一個對象我們必將其定義爲一個struct。
Go語言隻有一種控製可見性的手段大寫首字母的標識符會從定義它們的包中被導出小寫字母的則不會。這種限製包內成員的方式同樣適用於struct或者一個類型的方法。因而如果我們想要封裝一個對象我們必將其定義爲一個struct。
這也就是前面的小節中IntSet被定義爲struct類型的原因盡管它隻有一個字段