回到简体

This commit is contained in:
chai2010
2016-02-15 11:06:34 +08:00
parent 9e878f9944
commit 2b37b23285
177 changed files with 2354 additions and 2354 deletions

View File

@@ -1,6 +1,6 @@
## 6.3. 通嵌入結構體來擴展類
## 6.3. 通嵌入结构体来扩展类
看看ColoredPoint這個類型:
看看ColoredPoint这个类型:
<u><i>gopl.io/ch6/coloredpoint</i></u>
```go
@@ -14,7 +14,7 @@ type ColoredPoint struct {
}
```
完全可以ColoredPoint定義爲一個有三字段的struct但是我們卻將Point這個類型嵌入到ColoredPoint提供X和Y這兩個字段。像我在4.4中看到的那樣,內嵌可以使我在定ColoredPoint得到一句法上的簡寫形式,使其包含Point型所具有的一切字段,然再定一些自己的。如果我想要的,我可以直接認爲通過嵌入的字段就是ColoredPoint自身的字段而完全不需要在調用時指出Point比如下面這樣
完全可以ColoredPoint定义为一个有三字段的struct但是我们却将Point这个类型嵌入到ColoredPoint提供X和Y这两个字段。像我在4.4中看到的那样,内嵌可以使我在定ColoredPoint得到一句法上的简写形式,使其包含Point型所具有的一切字段,然再定一些自己的。如果我想要的,我可以直接认为通过嵌入的字段就是ColoredPoint自身的字段而完全不需要在调用时指出Point比如下面这样
```go
var cp ColoredPoint
@@ -24,7 +24,7 @@ cp.Point.Y = 2
fmt.Println(cp.Y) // "2"
```
對於Point中的方法我也有似的用法,我可以把ColoredPoint類型當作接收器來調用Point里的方法使ColoredPoint里沒有聲明這些方法:
对于Point中的方法我也有似的用法,我可以把ColoredPoint类型当作接收器来调用Point里的方法使ColoredPoint里没有声明这些方法:
```go
red := color.RGBA{255, 0, 0, 255}
@@ -37,15 +37,15 @@ q.ScaleBy(2)
fmt.Println(p.Distance(q.Point)) // "10"
```
Point的方法也被引入了ColoredPoint。用這種方式,嵌可以使我們定義字段特别多的複雜類型,我可以字段先按小型分,然後定義小類型的方法,之再把它們組合起
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
```
ColoredPoint不是一Point但他"has a"Point且它有Point里引入的Distance和ScaleBy方法。如果你喜歡從實現的角度來考慮問題,內嵌字段會指導編譯器去生成外的包方法來委託已經聲明好的方法,和下面的形式是等的:
ColoredPoint不是一Point但他"has a"Point且它有Point里引入的Distance和ScaleBy方法。如果你喜欢从实现的角度来考虑问题,内嵌字段会指导编译器去生成外的包方法来委托已经声明好的方法,和下面的形式是等的:
```go
func (p ColoredPoint) Distance(q Point) float64 {
@@ -57,9 +57,9 @@ func (p *ColoredPoint) ScaleBy(factor float64) {
}
```
Point.Distance被第一個包裝方法調用時它的接收器值是p.Point而不是p然了在Point的方法里,你是訪問不到ColoredPoint的任何字段的。
Point.Distance被第一个包装方法调用时它的接收器值是p.Point而不是p然了在Point的方法里,你是访问不到ColoredPoint的任何字段的。
型中嵌的匿名字段也可能是一命名型的指針,這種情況下字段和方法會被間接地引入到前的型中(譯註:訪問需要通過該指針指向的象去取)。添加這一層間接關繫讓我們可以共享通用的結構併動態地改變對象之間的關繫。下面這個ColoredPoint的聲明內嵌了一*Point的指
型中嵌的匿名字段也可能是一命名型的指针,这种情况下字段和方法会被间接地引入到前的型中(译注:访问需要通过该指针指向的象去取)。添加这一层间接关系让我们可以共享通用的结构并动态地改变对象之间的关系。下面这个ColoredPoint的声明内嵌了一*Point的指
```go
type ColoredPoint struct {
@@ -75,7 +75,7 @@ p.ScaleBy(2)
fmt.Println(*p.Point, *q.Point) // "{2 2} {2 2}"
```
struct型也可能有多匿名字段。我們將ColoredPoint定義爲下面這樣
struct型也可能有多匿名字段。我们将ColoredPoint定义为下面这样
```go
type ColoredPoint struct {
@@ -84,11 +84,11 @@ type ColoredPoint struct {
}
```
後這種類型的值便會擁有Point和RGBA型的所有方法,以及直接定在ColoredPoint中的方法。當編譯器解析一個選擇器到方法比如p.ScaleBy首先去找直接定義在這個類型里的ScaleBy方法找被ColoredPoint的嵌字段引入的方法,然去找Point和RGBA的嵌字段引入的方法,然一直遞歸向下找。如果選擇器有二性的話編譯器會報錯,比如你在同一里有兩個同名的方法。
后这种类型的值便会拥有Point和RGBA型的所有方法,以及直接定在ColoredPoint中的方法。当编译器解析一个选择器到方法比如p.ScaleBy首先去找直接定义在这个类型里的ScaleBy方法找被ColoredPoint的嵌字段引入的方法,然去找Point和RGBA的嵌字段引入的方法,然一直递归向下找。如果选择器有二性的话编译器会报错,比如你在同一里有两个同名的方法。
方法能在命名型(像Point)或者指向型的指上定,但是多虧了內嵌,有些候我們給匿名struct類型來定義方法也有了手段。
方法能在命名型(像Point)或者指向型的指上定,但是多亏了内嵌,有些候我们给匿名struct类型来定义方法也有了手段。
下面是一小trick。這個例子展示了簡單的cache其使用兩個包級别的變量來實現,一mutex互斥量(§9.2)和它所操作的cache
下面是一小trick。这个例子展示了简单的cache其使用两个包级别的变量来实现,一mutex互斥量(§9.2)和它所操作的cache
```go
var (
@@ -104,7 +104,7 @@ func Lookup(key string) string {
}
```
下面這個版本在功能上是一致的,但將兩個包級吧的量放在了cache這個struct一組內
下面这个版本在功能上是一致的,但将两个包级吧的量放在了cache这个struct一组内
```go
var cache = struct {
@@ -123,4 +123,4 @@ func Lookup(key string) string {
}
```
們給新的量起了一更具表性的名字cache。因sync.Mutex字段也被嵌入到了這個struct里其Lock和Unlock方法也就都被引入到了這個匿名結構中了,這讓我們能夠以一個簡單明了的語法來對其進行加鎖解鎖操作。
们给新的量起了一更具表性的名字cache。因sync.Mutex字段也被嵌入到了这个struct里其Lock和Unlock方法也就都被引入到了这个匿名结构中了,这让我们能够以一个简单明了的语法来对其进行加锁解锁操作。