面向对象
方法:
方法就是指定接受者的函数
匿名字段:
如果匿名字段中有重复属性,默认采用就近原则
如果需要给匿名字段内(子段的)属性赋值,可以 子类.父类.属性名赋值
匿名字段可以多重继承
指针字段使用前需要创建空间
给匿名字段定义变量名就是实名字段
封装:
封装就是将经常用的代码,整合成一个函数供程序调用。
封装可以增加代码的复用性,减少冗余。
func main() {
println(AddOpt(10, 20))
}
func AddOpt(n1, n2 int) int {
return n1 + n2
}
继承:
如果匿名字段实现了一个方法,那么包含这个匿名字段的结构体也就继承了这个方法。
实名字段不会继承,需要实名调用。
func main() {
a := AddOpt{Operate{8, 2}}
println(a.Result())
}
type Operate struct {
n1 int
n2 int
}
type AddOpt struct {
Operate
}
func (a *AddOpt) Result() int {
return a.n1 + a.n2
}
重写:
和匿名字段冲突一样的道理,我们可以在父类定义一个重名的方法,程序调用时也是采取就近原则。
接口的实现:
接口就是一种标准,如果一个对象(结构体)符合这个标准,就能通过接口操作该对象的方法。
任意的类型都实现了空interface(我们这样定义:interface{}),也就是包含0个method的interface。
可以通过将对象赋值给接头实现用接口调用对象的方法。
实现了接口的所有方法
参数类型、数量完全相同
返回值类型、数量完全相同
结构体必须实现接口内定义的所有方法,并且符合上述标准(才能实现该接口)
结构体方法如没在接口中定义,该方法不能通过接口调用(不影响正常使用)
接口名默认后缀为er
func main() {
// 创建接口
var c CalcEr
// 创建对象
a := AddOpt{Operate{1, 2}}
// 将对象赋值给接口
c = &a
// 使用接口调用对象的方法
sum := c.Result()
fmt.Println(sum)
}
type CalcEr interface {
Result() int
}
type Operate struct {
n1 int
n2 int
}
type AddOpt struct {
Operate
}
func (a *AddOpt) Result() int {
return a.n1 + a.n2
}
多态:
通过定义一个普通函数,参数为接口,该接口就实现了多态。
func main() {
var c CalcEr
a := AddOpt{Operate{1, 2}}
c = &a
Result(c)
}
// 将接口类型作为参数
func Result(c CalcEr) {
fmt.Println(c.Result())
}
type CalcEr interface {
Result() int
}
type Operate struct {
n1 int
n2 int
}
type AddOpt struct {
Operate
}
func (a *AddOpt) Result() int {
return a.n1 + a.n2
}
interface{}数据类型:
interface{}可以用来接收任意数据类型。
接口不能使用自动类型推导。
类型断言:
value, ok := element.(T)
如果如果类型正确ok为true,value为断言类型对应值
如果如果类型正确ok为false,value为断言类型默认空值