go面向对象2
类属性和成员方法可见性
不管是变量、函数,还是自定义类的属性和成员方法,它们的可见性都是根据其首字母的大小写来决定的,如果变量名、属性名、函数名或方法名首字母大写,就可以在包外直接访问这些变量、属性、函数和方法,否则只能在包内访问,因此 Go 语言类属性和成员方法的可见性都是包一级的
通过首字母大小写来控制
通过私有化提示代码的安全性
通过定义构造函数来封装他们的初始化过程,然后把属性名首字母小写进行私有化
animal.go
package animal
type Animal struct{
name string
}
func NewAnimal(name string) Animal {
return Animal{name:name}
}
func (a Animal) Call() string {
return "动物的叫声"
}
func (a Animal) FavorFood() string {
return "爱吃的食物"
}
func (a Animal) GetName() string {
return a.name
}
//属性名称首字母变成小写了,变成了私有的了
要完成类的初始化 需要调用构造函数来实现
animail := NewAnimal("中华田园犬")
接口定义及实现
一个类只要实现了某个接口要求的所有方法,我们就说这个类实现了该接口
定义一个类 File 并实现 Read Write Seek Close()
type File struct{
}
func (f *File) Read(buf []byte) (n int,err error)
func (f *File) Write(buf []byte) (n int,err error)
func (f *File) Seek(off int64) (pos int64,err error)
func (f *File) Close() error
go语言通过关键字 interface 来声明接口 ,花括号内包含的是待实现的方法集合
type IFile interface {
Read(buf []byte)(n int,err error)
Write(buf []byre) (n int,err error)
Seek(off int64,whence int) (pos int64,err error)
Close() error
}
type IReader interface {
Read(buf []byte) (n int, err error)
}
File实现了这些接口 因为file 实现了上述所有接口声明的方法
通过组合实现接口继承
go也支持类似接口继承的特性 通过组合来完成
例子
type A interface {
Foo()
}
type B interface {
A
Bar()
}
然后我们定义一个类 T 实现接口 B
type T strcut {}
func (t T) Foo(){
fmt.Println("call Foo funciton from interface a")
}
func (t T) Bar(){
fmt.Println("call bar function from interface b")
}
接口组合是匿名类型组合的一个特定的场景(没有显式的为组合类型设置对应的属性名称) 只包含方法 不包含属性
例子
type Reader interface{
Read(p []byte)(n int,err error)
}
type Writer interface{
Write(p []byte) (n int, err error)
}
type ReadWriter interface {
Reader
Writer
}
六 , 接口赋值
接口赋值在go分为2种情况
1 将实现接口的类实例赋值给接口
2将一个接口赋值给另外一个接口
将类实例赋值给接口
只包含值方法
********在这补上为值类型定义成员方法 *********
Go 语言中的大多数类型都是值语义,包括:
- 基本类型,如布尔类型、整型、浮点型、字符串等;
- 复合类型,如数组、结构体等(切片、字典、指针和通道都是引用语义)
-
Go 语言中的大多数类型都是值语义,包括:
- 基本类型,如布尔类型、整型、浮点型、字符串等;
- 复合类型,如数组、结构体等(切片、字典、指针和通道都是引用语义)
所有值语义类型都支持定义成员方法,包括内置基本类型。例如,我们可以为整型新增比较方法 Equal
,
不过在此之前,需要将基本类型通过 type
关键字设置为新的类型:
type Integer int
func (a Integer) Equal(b Interger) bool{
return a == b
}
*********end********
type Integer int //为基本类型添加成员方法时定义过的Integer类
func (a Integer) Add(b Integer) Integer {
return a+b
}
func (a Integer) Multiplay(b Integer) Integer {
return a*b
}
type Math interface {
Add(i Integer) Integer
Multiplay(i Integer) Integer
}
Integer类型实现了 Math接口 然后我们 就可以把Integer 类型的实例a 赋值给Math接口类型变量m
var a Integer =1
var m Math = a
fmt.Println(m.Add(1))
对于值方法 进行接口赋值时传递 a实例的指针引用也是可以的
var a Integer =1
var m Math = &a
fmt.Println(m.Add(1))
因为对于非指针方法 go底层会自动生成一个与之对于的指针成员方法
func (a *Integer) Add()
func (a *Integer) Multiplay( i Integer) Integer{
return (*a).Multiplay(i)
包含指针方法,接口赋值时 就只能传递指针类型的变量了
type Integer int
func (a *Integer) Add(b Integer){
*a = *a +b
}
var a Interger =1
var m Math = &a
将接口赋值给接口
在go语言中 只要2个接口拥有相同的方法列表 那么他们就是等同的 可以相互赋值
方法子集
如果接口a的方法列表是接口b方法列表的子集 那么接口b 可以赋值给接口a