匿名组合-golang
来源:互联网 发布:apache实现负载均衡 编辑:程序博客网 时间:2024/06/05 09:37
匿名组合
golang也提供了继承机制,但采用组合的文法,因此称为匿名组合。与其他语言不同, golang很清晰地展示出类的内存布局是怎样的。
• 非指针方式组合
▶ 基本语法
// 基类type Base struct { // 成员变量}func (b *Base) 函数名(参数列表) (返回值列表) { // 函数体}// 派生类type Derived struct { Base // 成员变量}func (b *Derived) 函数名(参数列表) (返回值列表) { // 函数体}
▶ 继承规则
√ 在派生类没有改写基类的成员方法时,相应的成员方法被继承。
√ 派生类可以直接调用基类的成员方法,譬如基类有个成员方法为Base.Func(),那么Derived.Func()等同于Derived.Base.Func()
√ 倘若派生类的成员方法名与基类的成员方法名相同,那么基类方法将被覆盖或叫隐藏,譬如基类和派生类都有成员方法Func(),那么Derived.Func()将只能调用派生类的Func()方法,如果要调用基类版本,可以通过Derived.Base.Func()来调用。
▪ 示例如下
package mainimport "fmt"type Base struct {}func (b *Base) Func1() { fmt.Println("Base.Func1() was invoked!")}func (b *Base) Func2() { fmt.Println("Base.Func2() was invoked!")}type Derived struct { Base}func (d *Derived) Func2() { fmt.Println("Derived.Func2() was invoked!")}func (d *Derived) Func3() { fmt.Println("Derived.Func3() was invoked!")}func main() { d := &Derived{} d.Func1() // Base.Func1() was invoked! d.Base.Func1() // Base.Func1() was invoked! d.Func2() // Derived.Func2() was invoked! d.Base.Func2() // Base.Func2() was invoked! d.Func3() // Derived.Func3() was invoked!}
▶ 内存布局
√ golang很清晰地展示类的内存布局是怎样的,即Base的位置即基类成员展开的位置。
√ golang还可以随心所欲地修改内存布局,即Base的位置可以出现在派生类的任何位置。
▪ 示例如下
package mainimport "fmt"type Base struct { BaseName string}func (b *Base) PrintName() { fmt.Println(b.BaseName)}type Derived struct { DerivedName string Base}func (d *Derived) PrintName() { fmt.Println(d.DerivedName)}func main() { d := &Derived{} d.BaseName = "BaseStruct" d.DerivedName = "DerivedStruct" d.Base.PrintName() // BaseStruct d.PrintName() // DerivedStruct}
• 指针方式组合
▶ 基本语法
// 基类type Base struct { // 成员变量}func (b *Base) 函数名(参数列表) (返回值列表) { // 函数体}// 派生类type Derived struct { *Base // 成员变量}func (b *Derived) 函数名(参数列表) (返回值列表) { // 函数体}
▶ 继承规则
√ 基类采用指针方式的组合,依然具有派生的效果,只是派生类创建实例的时候需要外部提供一个基类实例的指针。
√ 其他规则与非指针方式组合一致。
▪ 示例如下
package mainimport ( "fmt" "log" "os")type MyJob struct { Command string *log.Logger}func (job *MyJob) Start() { job.Println("job started!") // job.Logger.Println fmt.Println(job.Command) job.Println("job finished!") // job.Logger.Println}func main() { logFile, err := os.OpenFile("./job.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0) if err != nil { fmt.Println("%s", err.Error()) return } defer logFile.Close() logger := log.New(logFile, "[info]", log.Ldate|log.Ltime|log.Llongfile) job := MyJob{"programming", logger} job.Start() job.Println("test finished!") // job.Logger.Println}
在经过合适的赋值后,MyJob类型的所有成员方法可以很方便地借用所有log.Logger提供的方法。这对于MyJob的实现者来说,根本就不用意识到log.Logger类型的存在,这就是匿名组合的一个魅力所在。
一些总结
• 名字覆盖
上面说明了派生类成员方法名与基类成员方法名相同时基类方法将被覆盖的情况,这对于成员变量名来说,规则也是一致的。
package mainimport "fmt"type Base struct { Name string}type Derived struct { Base Name string}func main() { d := &Derived{} d.Name = "Derived" d.Base.Name = "Base" fmt.Println(d.Name) // Derived fmt.Println(d.Base.Name) // Base}
• 名字冲突
匿名组合相当于以其类型名称(去掉包名部分)作为成员变量的名字。那么按此规则,类型中如果存在两个同名的成员,即使类型不同,但我们预期会收到编译错误。
package mainimport "log"type Logger struct { Level int}type MyJob struct { *Logger Name string *log.Logger // duplicate field Logger}func main() { job := &MyJob{}}
原文链接
- golang中匿名组合
- 匿名组合-golang
- golang 匿名函数用法
- golang 中的 "继承" -----组合
- golang 组合算法
- golang 组合和接口
- golang匿名函数(闭包)
- golang利用组合实现继承
- golang匿名函数和闭包
- [Golang]设计模式实践:组合(Composite)
- golang设计模式(3)组合模式
- Go面向对象编程之匿名组合
- golang defer 语句匿名函数和具名函数的区别
- Golang同步:条件变量和锁组合使用
- golang语法总结(二十):struct组合
- GOLANG接口适配,组合方式的灵活接口演化
- [译]Golang中JSON和结构体的组合使用
- Go语言以匿名组合的方式实现继承
- The MRC database dictionary之MRC_words
- SQLite与Android的数据交互
- Quartz 入门(1)
- CameraDemo
- Transaction rolled back because it has been marked as rollback-only解决方案
- 匿名组合-golang
- JAVAWEB开发之redis学习(八)——redis事务
- 字节流/输入输出
- Day20-jsp & el & jstl
- Intent隐式与显式
- 关于用深度学习做answer selection的论文
- 使用TableView进行分组
- HTTP中GET与POST的区别
- 二分图判定