|
|
@@ -416,7 +416,117 @@ func (n *NamedPoint) Abs() float64 {
|
|
|
|
|
|
然后仅在Mercedes类型上创建方法sayHiToMerkel()并调用它。
|
|
|
|
|
|
-** 10.6.6
|
|
|
+** 10.6.6 如何在类型中嵌入功能
|
|
|
+
|
|
|
+主要有两种方法来实现在类型中嵌入功能:
|
|
|
+
|
|
|
+A. 聚合(或组合):包含一个所需功能类型的具名字段
|
|
|
+B. 内嵌:内嵌(匿名地)所需功能类型,像前一节10.6.5 所示的那样
|
|
|
+
|
|
|
+为了使这些概念具体化,假设有一个Customer类型,我们想让它通过Log类型来包含日志功能,Log类型只是简单地包含一个累积的消息(当然它可以是复杂的)。如果想让特定类型都具备日志功能,你可以实现一个这样的Log类型,然后将它作为特定类型的一个字段,并提供Log(),它返回这个日志的引用。
|
|
|
+
|
|
|
+方式A可以通过如下方法实现(使用了10.7中的String()功能):
|
|
|
+
|
|
|
+Listing 10.19—embed_func1.go:
|
|
|
+```go
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+)
|
|
|
+
|
|
|
+type Log struct {
|
|
|
+ msg string
|
|
|
+}
|
|
|
+
|
|
|
+type Customer struct {
|
|
|
+ Name string
|
|
|
+ log *Log
|
|
|
+}
|
|
|
+
|
|
|
+func main() {
|
|
|
+ c := new(Customer)
|
|
|
+ c.Name = "Barak Obama"
|
|
|
+ c.log = new(Log)
|
|
|
+ c.log.msg = "1 - Yes we can!"
|
|
|
+ // shorter
|
|
|
+ c = &Customer{"Barak Obama", &Log{"1 - Yes we can!"}}
|
|
|
+ // fmt.Println(c) &{Barak Obama 1 - Yes we can!}
|
|
|
+ c.Log().Add("2 - After me the world will be a better place!")
|
|
|
+ //fmt.Println(c.log)
|
|
|
+ fmt.Println(c.Log())
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func (l *Log) Add(s string) {
|
|
|
+ l.msg += "\n" + s
|
|
|
+}
|
|
|
+
|
|
|
+func (l *Log) String() string {
|
|
|
+ return l.msg
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Customer) Log() *Log {
|
|
|
+ return c.log
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+输出:
|
|
|
+
|
|
|
+ 1 - Yes we can!
|
|
|
+ 2 - After me the world will be a better place!
|
|
|
+
|
|
|
+相对的方式B可能会像这样:
|
|
|
+
|
|
|
+```go
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+)
|
|
|
+
|
|
|
+type Log struct {
|
|
|
+ msg string
|
|
|
+}
|
|
|
+
|
|
|
+type Customer struct {
|
|
|
+ Name string
|
|
|
+ Log
|
|
|
+}
|
|
|
+
|
|
|
+func main() {
|
|
|
+ c := &Customer{"Barak Obama", Log{"1 - Yes we can!"}}
|
|
|
+ c.Add("2 - After me the world will be a better place!")
|
|
|
+ fmt.Println(c)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func (l *Log) Add(s string) {
|
|
|
+ l.msg += "\n" + s
|
|
|
+}
|
|
|
+
|
|
|
+func (l *Log) String() string {
|
|
|
+ return l.msg
|
|
|
+}
|
|
|
+
|
|
|
+func (c *Customer) String() string {
|
|
|
+ return c.Name + "\nLog:" + fmt.Sprintln(c.Log)
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+输出:
|
|
|
+
|
|
|
+ Barak Obama
|
|
|
+ Log:{1 - Yes we can!
|
|
|
+ 2 - After me the world will be a better place!}
|
|
|
+
|
|
|
+内嵌的类型不需要指针,Customer也不需要Add方法,它使用Log的Add方法,Customer有自己的String方法,并且在它里面调用了Log的String方法。
|
|
|
+
|
|
|
+如果内嵌类型嵌入了其他类型,也是可以的,那些类型的方法可以直接在外层类型中使用。
|
|
|
+
|
|
|
+因此一个好的策略是创建一些小的、可复用的类型作为一个工具箱,用于组成域类型。
|
|
|
+
|
|
|
+** 10.6.7 多根继承
|
|
|
|
|
|
## 链接
|
|
|
- [目录](directory.md)
|