Golang学习笔记1-组合和接口
2018-03-01 21:42
260 查看
主要内容
1.组合 2.接口 3.常见问题 4.总结
1.组合
Golang中没有OOP中继承的概念,取而代之的是组合,同样起到属性和方法继承 的作用,特别是匿名组合,其表现形式和继承的行为类似,但是却有很多不同的地方,相对于继承、多态这些典型的OOP思想,组合显得更加简洁灵活。1.1.一般组合
type Wifi struct { Name string } type Phone struct { WifiMdl Wifi } func Test_Group(t *testing.T) { phone := Phone{} phone.WifiMdl = Wifi{ Name: "..." } ... }
这是一个简单的示例,直接将其他的类型作为自己的内部成员;那么新类型的实例就可以直接对此成员进行赋值和初始化;
1.2.匿名组合
当我们嵌入一个类型,这个类型的方法就变成了外部类型的方法,但是当它被调用时,方法的接受者是内部类型(嵌入类型),而非外部类型。— Effective Go理解了这句话也就理解匿名组合:简单地可以理解为,内部类型的成员名可理解为内部类型名,在外部类型未定义相同名称的属性和方法时,内部方法可提升为外部类型的属性和方法,但实际上,属性和方法的所有者和调用的接受仍然为内部类型
// 内部类型 type People struct { Name string } func (p *People) GetName() { log.Print(p.Name) } // 外部类型 type Man struct { People } func Test_Group(t *testing.T) { man := Man{} man.Name = "villare" man.GetName() }
匿名组合,即嵌入的类型没有自己的属性名,这种方式的组合和一般的组合最大的不同在于,外部类型的实例可以直接通过自身访问内部类型的属性和方法,“看上去外部类型作为属性和方法的所有者”,形式上与继承的类似;
特别的,如果内部类型也为指针
// 内部类型 type People struct { Name string } func (p *People) GetName() { log.Print(p.Name) } // 外部类型 type Man struct { *People } func Test_Group(t *testing.T) { man := Man{} //以下代码报错(invalid memory address or nil pointer dereference...) //先初始化 man := Man{&People{},} man.Name = "villare" man.GetName() }
指针类型的匿名组合在直接调用内部类型的方法时,会出现地址未分配的错误;可见,指针类型的匿名组合需要在外部类型初始化的同时进行手动初始化,不会自动初始化内部类型;
由此可见,匿名组合中内部方法的接受者实际上还是内部类型;
2.接口
2.1.接口的定义
type People interface { Sex() }
接口的定义和其他语言有相似之处,直接定义接口方法,不过不支持静态成员和默认方法的定义形式;
由于golang接口的实现形式使得它没必要支持这些特性
2.2.接口的实现
type People interface { Sex() }
type Man struct {}
func (m *Man) Sex() {
log.Print("Man")
}
type Woman struct {}
func (m *Woman) Sex() {
log.Print("Woman")
}
func Test_Inter(t *testing.T) {
var t1 People
t1 = new(Man)
t1.Sex()
t1 = new(Woman)
t1.Sex()
}
golang的接口实现遵循一个原则:如果一个类型实现了接口定义的所有方法,那么就认为此类型实现了这个接口
golang中方法不能重名,不支持重载
golang不使用接口指针,直接使用接口类型,注意和java、c++的区别
3.常见问题
3.1.组合中的访问控制
golang默认的访问控制规则是:首字母大写(Public),首字母小写(private)对于组合来说,内部类型的私有成员在外部类型中可见,但是仍然为私有成员(不可通过实例直接访问)
3.2.嵌入冲突
type Time struct { Name string } // 正确示例 type UTC struct { time.Time T2 Time } // 错误示例 type UTC struct { time.Time Time }
在嵌入多个类型时,保证成员名不同,匿名组合的成员名为类型名称
即使不同包路径不同,只要类型名相同,匿名组合均有冲突
3.2.匿名组合的冲突
注意一点,成员和方法的优先级:外部类型 > 内部类型 > 内部类型的内部类型 > …
如果出现歧义(Ambiguous),通过加类型名的形式调用,明确一点“属性和方法的所有者和调用者均属于内部方法”。
关注下面一个实例
type People struct { Name string } func (p *People) GetSex() { log.Print("Man Or Woman") } type Man struct { People } func (p *Man) GetSex() { log.Print("Man") } type Child struct { Man } func Test_Group(t *testing.T) { cld := Child{} cld.GetSex() cld.Man.GetSex() cld.People.GetSex() } //输出为 Man Man Man Or Woman
4.总结
总的来说,golang组合和接口的两个概念还是相对比较好理解的,规则也更加契合主观认知,减少了理解和学习的成本;但在简洁的同时也并没有减弱golang语言本身的表达和设计能力;相关文章推荐
- Golang学习笔记 方法和接口
- golang学习的点点滴滴:接口组合
- Java学习笔记——继承、接口、多态
- Java学习笔记——接口的多实现技术
- prism4学习笔记5:INotifyPropertyChanged接口
- Seliverlight 中数据绑定INotifyPropertyChanged 接口的用法 .数据绑定IValueConvert的用法学习笔记
- MSP430学习笔记8-ST7920 12864液晶显示并行接口
- Java核心技术(第8版)学习笔记_接口与内部类
- java核心卷之接口学习笔记
- php学习笔记之--抽象类、接口与多态
- Java学习笔记之接口和抽象类
- [学习笔记]外部调用本地接口返回JSON数据
- 学习笔记---高等数学前置知识---数列、排列组合、解不等式
- 网络编程学习笔记(ICMPv6和IPv6套接口选项)
- 黑马程序员_java抽象类和接口学习笔记
- JAVAOOP第4章(接口)学习笔记
- 操作系统学习笔记:文件系统接口
- 1)Java学习笔记:接口和抽象类的异同
- 搭建本地数据接口(jsonserver)=>restful 学习笔记
- java学习记录笔记--多态,接口,UML简介