This commit is contained in:
chai2010
2016-01-02 21:17:21 +08:00
parent 8772a9c000
commit ba03c527c0
17 changed files with 63 additions and 29 deletions

View File

@@ -69,6 +69,7 @@ func (s *IntSet) String() string {
這里留意一下String方法是不是和3.5.4節中的intsToString方法很相似bytes.Buffer在String方法里經常這麽用。當你爲一個複雜的類型定義了一個String方法時fmt包就會特殊對待這種類型的值這樣可以讓這些類型在打印的時候看起來更加友好而不是直接打印其原始的值。fmt會直接調用用戶定義的String方法。這種機製依賴於接口和類型斷言在第7章中我們會詳細介紹。
現在我們就可以在實戰中直接用上面定義好的IntSet了
```go
var x, y IntSet
x.Add(1)
@@ -86,14 +87,17 @@ fmt.Println(x.Has(9), x.Has(123)) // "true false"
```
這里要註意我們聲明的String和Has兩個方法都是以指針類型*IntSet來作爲接收器的但實際上對於這兩個類型來説把接收器聲明爲指針類型也沒什麽必要。不過另外兩個函數就不是這樣了因爲另外兩個函數操作的是s.words對象如果你不把接收器聲明爲指針對象那麽實際操作的是拷貝對象而不是原來的那個對象。因此因爲我們的String方法定義在IntSet指針上所以當我們的變量是IntSet類型而不是IntSet指針時可能會有下面這樣讓人意外的情況
```go
fmt.Println(&x) // "{1 9 42 144}"
fmt.Println(x.String()) // "{1 9 42 144}"
fmt.Println(x) // "{[4398046511618 0 65536]}"
```
在第一個Println中我們打印一個*IntSet的指針這個類型的指針確實有自定義的String方法。第二Println我們直接調用了x變量的String()方法這種情況下編譯器會隱式地在x前插入&操作符這樣相當遠我們還是調用的IntSet指針的String方法。在第三個Println中因爲IntSet類型沒有String方法所以Println方法會直接以原始的方式理解併打印。所以在這種情況下&符號是不能忘的。在我們這種場景下你把String方法綁定到IntSet對象上而不是IntSet指針上可能會更合適一些不過這也需要具體問題具體分析。
練習6.1: 爲bit數組實現下面這些方法
```go
func (*IntSet) Len() int // return the number of elements
func (*IntSet) Remove(x int) // remove x from the set