回到简体

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 @@
## 7.3. 實現接口的
## 7.3. 实现接口的
個類型如果有一接口需要的所有方法,那麽這個類型就實現了這個接口。例如,\*os.File類型實現了io.ReaderWriterCloser和ReadWriter接口。\*bytes.Buffer實現了ReaderWriter和ReadWriter些接口,但是它沒有實現Closer接口因它不具有Close方法。Go的程序員經常會簡要的把一個具體的類型描述成一特定的接口型。舉個例子,\*bytes.Buffer是io.Writer\*os.Files是io.ReadWriter。
个类型如果有一接口需要的所有方法,那么这个类型就实现了这个接口。例如,\*os.File类型实现了io.ReaderWriterCloser和ReadWriter接口。\*bytes.Buffer实现了ReaderWriter和ReadWriter些接口,但是它没有实现Closer接口因它不具有Close方法。Go的程序员经常会简要的把一个具体的类型描述成一特定的接口型。举个例子,\*bytes.Buffer是io.Writer\*os.Files是io.ReadWriter。
接口指定的規則非常簡單:表達一個類型屬於某個接口隻要這個類型實現這個接口。所以:
接口指定的规则非常简单:表达一个类型属于某个接口只要这个类型实现这个接口。所以:
```go
var w io.Writer
@@ -15,18 +15,18 @@ rwc = os.Stdout // OK: *os.File has Read, Write, Close methods
rwc = new(bytes.Buffer) // compile error: *bytes.Buffer lacks Close method
```
這個規則甚至適用於等式右本身也是一接口
这个规则甚至适用于等式右本身也是一接口
```go
w = rwc // OK: io.ReadWriteCloser has Write method
rwc = w // compile error: io.Writer lacks Close method
```
ReadWriter和ReadWriteCloser包含所有Writer的方法所以任何實現了ReadWriter和ReadWriteCloser的型必定也實現了Writer接口
ReadWriter和ReadWriteCloser包含所有Writer的方法所以任何实现了ReadWriter和ReadWriteCloser的型必定也实现了Writer接口
一步學習前,必先解表示一個類型持有一方法中的細節。迴想在6.2章中,對於每一命名的具體類型T它一些方法的接收者是型T本身然而另一些是一*T的指針。還記得在T型的參數上調用一*T的方法是合法的隻要這個參數是一個變量;編譯器隱式的取了它的地址。但這僅僅是一個語法糖T型的值不有所有*T指的方法,那這樣它就可能隻實現更少的接口。
一步学习前,必先解表示一个类型持有一方法中的细节。回想在6.2章中,对于每一命名的具体类型T它一些方法的接收者是型T本身然而另一些是一*T的指针。还记得在T型的参数上调用一*T的方法是合法的只要这个参数是一个变量;编译器隐式的取了它的地址。但这仅仅是一个语法糖T型的值不有所有*T指的方法,那这样它就可能只实现更少的接口。
舉個例子可能更清晰一。在第6.5章中IntSet型的String方法的接收者是一個指針類型,所以我不能在一不能址的IntSet值上調用這個方法:
举个例子可能更清晰一。在第6.5章中IntSet型的String方法的接收者是一个指针类型,所以我不能在一不能址的IntSet值上调用这个方法:
```go
type IntSet struct { /* ... */ }
@@ -34,23 +34,23 @@ func (*IntSet) String() string
var _ = IntSet{}.String() // compile error: String requires *IntSet receiver
```
但是我可以在一IntSet值上調用這個方法:
但是我可以在一IntSet值上调用这个方法:
```go
var s IntSet
var _ = s.String() // OK: s is a variable and &s has a String method
```
然而,由於隻有*IntSet型有String方法所有也有*IntSet類型實現了fmt.Stringer接口
然而,由于只有*IntSet型有String方法所有也有*IntSet类型实现了fmt.Stringer接口
```go
var _ fmt.Stringer = &s // OK
var _ fmt.Stringer = s // compile error: IntSet lacks String method
```
12.8章包含了一打印出任意值的所有方法的程序,然可以使用godoc -analysis=type tool(§10.7.4)展示每個類型的方法和具體類型和接口之間的關繫
12.8章包含了一打印出任意值的所有方法的程序,然可以使用godoc -analysis=type tool(§10.7.4)展示每个类型的方法和具体类型和接口之间的关系
就像信封封裝和隱藏信件起來一樣,接口型封裝和隱藏具體類型和它的值。使具體類型有其它的方法也有接口型暴露出的方法會被調用到:
就像信封封装和隐藏信件起来一样,接口型封装和隐藏具体类型和它的值。使具体类型有其它的方法也有接口型暴露出的方法会被调用到:
```go
os.Stdout.Write([]byte("hello")) // OK: *os.File has Write method
@@ -62,9 +62,9 @@ w.Write([]byte("hello")) // OK: io.Writer has Write method
w.Close() // compile error: io.Writer lacks Close method
```
有更多方法的接口比如io.ReadWriter和少一些方法的接口型,例如io.Reader進行對比;更多方法的接口類型會告訴我們更多關於它的值持有的信息,併且對實現它的型要求更加格。那麽關於interface{}型,它有任何方法,請講出哪些具體的類型實現了它?
有更多方法的接口比如io.ReadWriter和少一些方法的接口型,例如io.Reader进行对比;更多方法的接口类型会告诉我们更多关于它的值持有的信息,并且对实现它的型要求更加格。那么关于interface{}型,它有任何方法,请讲出哪些具体的类型实现了它?
看上去好像有用,但實際上interface{}被稱爲空接口型是不可或缺的。因空接口類型對實現它的類型沒有要求,所以我可以任意一個值賦給空接口型。
看上去好像有用,但实际上interface{}被称为空接口型是不可或缺的。因空接口类型对实现它的类型没有要求,所以我可以任意一个值赋给空接口型。
```go
var any interface{}
@@ -75,29 +75,29 @@ any = map[string]int{"one": 1}
any = new(bytes.Buffer)
```
管不是很明顯,從本書最早的的例子中我就已在使用空接口型。它允像fmt.Println或者5.7章中的errorf函接受任何型的參數
管不是很明显,从本书最早的的例子中我就已在使用空接口型。它允像fmt.Println或者5.7章中的errorf函接受任何型的参数
對於創建的一interface{}值持有一booleanfloatstringmappointer或者任意其它的型;我們當然不能直接它持有的值做操作,因interface{}有任何方法。我們會在7.10章中到一種用類型斷言來獲取interface{}中值的方法。
对于创建的一interface{}值持有一booleanfloatstringmappointer或者任意其它的型;我们当然不能直接它持有的值做操作,因interface{}有任何方法。我们会在7.10章中到一种用类型断言来获取interface{}中值的方法。
接口實現隻依賴於判斷的兩個類型的方法,所以有必要定義一個具體類型和它實現的接口之間的關繫。也就是説,嚐試文檔化和斷言這種關繫幾乎沒有用,所以併沒有通程序強製定義。下面的定義在編譯期斷言一*bytes.Buffer的值實現了io.Writer接口型:
接口实现只依赖于判断的两个类型的方法,所以有必要定义一个具体类型和它实现的接口之间的关系。也就是说,尝试文档化和断言这种关系几乎没有用,所以并没有通程序强制定义。下面的定义在编译期断言一*bytes.Buffer的值实现了io.Writer接口型:
```go
// *bytes.Buffer must satisfy io.Writer
var w io.Writer = new(bytes.Buffer)
```
任意*bytes.Buffer的值甚至包括nil通(*bytes.Buffer)(nil)進行顯示的轉換都實現了這個接口,所以我不必分配一新的量。且因爲我們絶不會引用量w可以使用空標識符來來進行代替。的看,這些變化可以讓我們得到一個更樸素的版本:
任意*bytes.Buffer的值甚至包括nil通(*bytes.Buffer)(nil)进行显示的转换都实现了这个接口,所以我不必分配一新的量。且因为我们绝不会引用量w可以使用空标识符来来进行代替。的看,这些变化可以让我们得到一个更朴素的版本:
```go
// *bytes.Buffer must satisfy io.Writer
var _ io.Writer = (*bytes.Buffer)(nil)
```
非空的接口型比如io.Writer常被指針類型實現,尤其當一個或多接口方法像Write方法那樣隱式的接收者帶來變化的候。一個結構體的指是非常常的承方法的型。
非空的接口型比如io.Writer常被指针类型实现,尤其当一个或多接口方法像Write方法那样隐式的接收者带来变化的候。一个结构体的指是非常常的承方法的型。
但是不意味着有指針類型滿足接口型,甚至一些有置方法的接口型也可能被Go言中其它的引用類型實現。我們已經看過slice型的方法(geometry.Path, §6.1)和map型的方法(url.Values, §6.2.1)後面還會看到函數類型的方法的例子(http.HandlerFunc, §7.7)。甚至基本的型也可能會實現一些接口;就如我在7.4章中看到的time.Duration類型實現了fmt.Stringer接口。
但是不意味着有指针类型满足接口型,甚至一些有置方法的接口型也可能被Go言中其它的引用类型实现。我们已经看过slice型的方法(geometry.Path, §6.1)和map型的方法(url.Values, §6.2.1)后面还会看到函数类型的方法的例子(http.HandlerFunc, §7.7)。甚至基本的型也可能会实现一些接口;就如我在7.4章中看到的time.Duration类型实现了fmt.Stringer接口。
個具體的類型可能實現了很多不相的接口。考在一個組織出售字文化品比如音樂,電影和籍的程序中可能定了下列的具體類型:
个具体的类型可能实现了很多不相的接口。考在一个组织出售字文化品比如音乐,电影和籍的程序中可能定了下列的具体类型:
```
Album
@@ -109,7 +109,7 @@ TVEpisode
Track
```
可以把每抽象的特用接口表示。一些特性對於所有的些文化品都是共通的,例如標題,創作日期和作者列表。
可以把每抽象的特用接口表示。一些特性对于所有的些文化品都是共通的,例如标题,创作日期和作者列表。
```go
type Artifact interface {
@@ -118,7 +118,7 @@ type Artifact interface {
Created() time.Time
}
```
其它的一些特性隻對特定型的文化品才有。和文字排版特性相關的隻有books和magazines還有隻有movies和TV集和屏幕分辨率相
其它的一些特性只对特定型的文化品才有。和文字排版特性相关的只有books和magazines还有只有movies和TV集和屏幕分辨率相
```go
type Text interface {
@@ -139,7 +139,7 @@ type Video interface {
}
```
些接口不止是一有用的方式來分組相關的具體類型和表示他們之間的共同特定。我們後面可能會發現其它的分組。舉例,如果我們發現我們需要以同的方式理Audio和Video可以定義一個Streamer接口代表它們之間相同的部分而不必對已經存在的型做改
些接口不止是一有用的方式来分组相关的具体类型和表示他们之间的共同特定。我们后面可能会发现其它的分组。举例,如果我们发现我们需要以同的方式理Audio和Video可以定义一个Streamer接口代表它们之间相同的部分而不必对已经存在的型做改
```go
type Streamer interface {
@@ -149,4 +149,4 @@ type Streamer interface {
}
```
每一個具體類型的組基於它們相同的行可以表示成一接口型。不像基於類的語言,他們一個類實現的接口集合需要進行顯式的定在Go言中我可以在需要的候定義一個新的抽象或者特定特點的組,而不需要改具體類型的定義。當具體的類型來自不同的作者時這種方式特别有用。然也確實沒有必要在具體的類型中指出些共性。
每一个具体类型的组基于它们相同的行可以表示成一接口型。不像基于类的语言,他们一个类实现的接口集合需要进行显式的定在Go言中我可以在需要的候定义一个新的抽象或者特定特点的组,而不需要改具体类型的定义。当具体的类型来自不同的作者时这种方式特别有用。然也确实没有必要在具体的类型中指出些共性。