make loop

This commit is contained in:
chai2010
2015-12-18 14:49:31 +08:00
parent 9fde1ff772
commit f9ac065e47
106 changed files with 725 additions and 725 deletions

View File

@@ -1,6 +1,6 @@
## 6.1. 方法聲明
在函數聲明時,在其名字之前放上一個變量,卽是一個方法。這個附加的參數會將該函數附加到這種類型上,卽相當於爲這種類型定義了一個獨的方法。
在函數聲明時,在其名字之前放上一個變量,卽是一個方法。這個附加的參數會將該函數附加到這種類型上,卽相當於爲這種類型定義了一個獨的方法。
下面來寫我們第一個方法的例子這個例子在package geometry下
@@ -25,9 +25,9 @@ func (p Point) Distance(q Point) float64 {
```
上面的代碼那個附加的參數p叫做方法的接收器(receiver),早期的面向對象語言留下的遺將調用一個方法稱爲“向一個對象發送消息”。
上面的代碼那個附加的參數p叫做方法的接收器(receiver),早期的面向對象語言留下的遺將調用一個方法稱爲“向一個對象發送消息”。
在Go語言中我們不會像其它語言那樣用this或者self作爲接收器我們可以任意的選擇接收器的名字。由於接收器的名字經常會被使用到所以保持其在方法間傳遞時的一性和簡短性是不錯的主意。這的建議是可以使用其類型的第一個字母,比如這使用了Point的首字母p。
在Go語言中我們不會像其它語言那樣用this或者self作爲接收器我們可以任意的選擇接收器的名字。由於接收器的名字經常會被使用到所以保持其在方法間傳遞時的一性和簡短性是不錯的主意。這的建議是可以使用其類型的第一個字母,比如這使用了Point的首字母p。
在方法調用過程中,接收器參數一般會在方法名之前齣現。這和方法聲明是一樣的,都是接收器參數在方法名字之前。下面是例子:
@@ -38,11 +38,11 @@ fmt.Println(Distance(p, q)) // "5", function call
fmt.Println(p.Distance(q)) // "5", method call
```
可以看到上面的兩個函數調用都是Distance但是卻沒有發生突。第一個Distance的調用實際上用的是包級的函數geometry.Distance而第二個則是使用剛剛聲明的Point調用的是Point類下聲明的Point.Distance方法。
可以看到上面的兩個函數調用都是Distance但是卻沒有發生突。第一個Distance的調用實際上用的是包級的函數geometry.Distance而第二個則是使用剛剛聲明的Point調用的是Point類下聲明的Point.Distance方法。
這種p.Distance的表達式叫做選擇器因爲他會選擇合適的對應p這個對象的Distance方法來執行。選擇器也會被用來選擇一個struct類型的字段比如p.X。由於方法和字段都是在同一命名空間所以如果我們在這聲明一個X方法的話編譯器會報錯因爲在調用p.X時會有歧義(譯註:這確實挺奇怪的)。
這種p.Distance的表達式叫做選擇器因爲他會選擇合適的對應p這個對象的Distance方法來執行。選擇器也會被用來選擇一個struct類型的字段比如p.X。由於方法和字段都是在同一命名空間所以如果我們在這聲明一個X方法的話編譯器會報錯因爲在調用p.X時會有歧義(譯註:這確實挺奇怪的)。
因爲每種類型都有其方法的命名空間我們在用Distance這個名字的時候不同的Distance調用指向了不同類型的Distance方法。讓我們來定義一個Path類型這個Path代表一個段的集合,且也給這個Path定義一個叫Distance的方法。
因爲每種類型都有其方法的命名空間我們在用Distance這個名字的時候不同的Distance調用指向了不同類型的Distance方法。讓我們來定義一個Path類型這個Path代表一個段的集合,且也給這個Path定義一個叫Distance的方法。
```Go
// A Path is a journey connecting the points with straight lines.
@@ -59,9 +59,9 @@ func (path Path) Distance() float64 {
}
```
Path是一個命名的slice類型而不是Point那樣的struct類型然而我們依然可以爲它定義方法。在能夠給任意類型定義方法這一點上Go和很多其它的面向對象的語言不太一樣。因此在Go語言我們爲一些簡單的數值、字符串、slice、map來定義一些附加行爲很方便。方法可以被聲明到任意類型隻要不是一個指或者一個interface。
Path是一個命名的slice類型而不是Point那樣的struct類型然而我們依然可以爲它定義方法。在能夠給任意類型定義方法這一點上Go和很多其它的面向對象的語言不太一樣。因此在Go語言我們爲一些簡單的數值、字符串、slice、map來定義一些附加行爲很方便。方法可以被聲明到任意類型隻要不是一個指或者一個interface。
兩個Distance方法有不同的類型。他們兩個方法之間沒有任何關繫管Path的Distance方法會在內部調用Point.Distance方法來計算每個連接鄰接點的段的長度。
兩個Distance方法有不同的類型。他們兩個方法之間沒有任何關繫管Path的Distance方法會在內部調用Point.Distance方法來計算每個連接鄰接點的段的長度。
讓我們來調用一個新方法,計算三角形的週長:
@@ -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"
@@ -87,4 +87,4 @@ fmt.Println(geometry.PathDistance(perim)) // "12", standalone function
fmt.Println(perim.Distance()) // "12", method of geometry.Path
```
譯註如果我們要用方法去計算perim的distance還需要去寫全geometry的包名和其函數名但是因爲Path這個變量定義了一個可以直接用的Distance方法所以我們可以直接寫perim.Distance()。相當於可以少打很多字作者應該是這個意思。因爲在Go包外調用函數需要帶上包名,還是挺麻煩的。
譯註如果我們要用方法去計算perim的distance還需要去寫全geometry的包名和其函數名但是因爲Path這個變量定義了一個可以直接用的Distance方法所以我們可以直接寫perim.Distance()。相當於可以少打很多字作者應該是這個意思。因爲在Go包外調用函數需要帶上包名,還是挺麻煩的。