回到简体

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,8 +1,8 @@
## 6.1. 方法
## 6.1. 方法
在函數聲明時,在其名字之前放上一個變量,是一方法。這個附加的參數會將該函數附加到這種類型上,卽相當於爲這種類型定了一個獨占的方法。
在函数声明时,在其名字之前放上一个变量,是一方法。这个附加的参数会将该函数附加到这种类型上,即相当于为这种类型定了一个独占的方法。
下面來寫我們第一方法的例子,這個例子在package geometry下
下面来写我们第一方法的例子,这个例子在package geometry下
<u><i>gopl.io/ch6/geometry</i></u>
```go
@@ -23,11 +23,11 @@ func (p Point) Distance(q Point) float64 {
}
```
上面的代里那附加的參數p叫做方法的接收器(receiver),早期的面向對象語言留下的遺産將調用一方法稱爲“向一個對象發送消息”。
上面的代里那附加的参数p叫做方法的接收器(receiver),早期的面向对象语言留下的遗产将调用一方法称为“向一个对象发送消息”。
在Go言中,我們併不會像其它言那用this或者self作接收器;我可以任意的選擇接收器的名字。由接收器的名字經常會被使用到,所以保持其在方法間傳遞時的一致性和短性是不的主意。里的建是可以使用其型的第一字母,比如里使用了Point的首字母p。
在Go言中,我们并不会像其它言那用this或者self作接收器;我可以任意的选择接收器的名字。由接收器的名字经常会被使用到,所以保持其在方法间传递时的一致性和短性是不的主意。里的建是可以使用其型的第一字母,比如里使用了Point的首字母p。
在方法調用過程中,接收器參數一般在方法名之前出現。這和方法明是一的,都是接收器參數在方法名字之前。下面是例子:
在方法调用过程中,接收器参数一般在方法名之前出现。这和方法明是一的,都是接收器参数在方法名字之前。下面是例子:
```Go
p := Point{1, 2}
@@ -36,11 +36,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.
@@ -57,11 +57,11 @@ 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方法来计算每个连接邻接点的线段的度。
讓我們來調用一新方法,算三角形的週長
让我们来调用一新方法,算三角形的周长
```Go
perim := Path{
@@ -73,9 +73,9 @@ perim := Path{
fmt.Println(perim.Distance()) // "12"
```
在上面兩個對Distance名字的方法的調用中,編譯器會根據方法的名字以及接收器來決定具體調用的是哪一個函數。第一例子中path[i-1]數組中的型是Point因此Point.Distance這個方法被調用;在第二例子中perim的型是Path因此Distance調用的是Path.Distance。
在上面两个对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"
@@ -85,4 +85,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里包外用函需要上包名,是挺麻的。