Golang非面向对象的语言:
- 封装:没有提供public等关键字,而是以大写字符开始来表示包外可见;
- 继承:没有implements等关键字,而是通过匿名组合(has-a)方式模拟继承;
- 多态:通过接口(interface)实现的一种duck typing类型
多态
通过Interface可实现多态继承(is-a);可用interface来代表对应的实现类来操作:
type CheckParamValid interface {
IsValueValid(v float64) bool
GetKeys() []string
}
func BuildCheckKey(key ...string) []string {
return key
}
func BuildLowerThreshold(lower float64, key ...string) *LowerCheckParam {
return &LowerCheckParam{
Keys: key,
Lower: lower,
}
}
func BuildRangeThreshold(lower float64, upper float64, key ...string) *RangeCheckParam {
return &RangeCheckParam{
Keys: key,
Lower: lower,
Upper: upper,
}
}
type RangeCheckParam struct {
Keys []string
Lower float64
Upper float64
}
func (this *RangeCheckParam) IsValueValid(v float64) bool {
return v >= this.Lower && v <= this.Upper
}
func (this *RangeCheckParam) GetKeys() []string {
return this.Keys
}
type LowerCheckParam struct {
Keys []string
Lower float64
}
func (this *LowerCheckParam) IsValueValid(v float64) bool {
return v >= this.Lower
}
func (this *LowerCheckParam) GetKeys() []string {
return this.Keys
}
func ParamCheckTest() {
thres := map[string][]CheckParamValid{
"face": []CheckParamValid{
&RangeCheckParam{BuildCheckKey("box", "width"), 10, 100},
&LowerCheckParam{BuildCheckKey("Score"), 0.1},
},
}
fmt.Println("To check")
for _, v := range thres {
for _, check := range v {
fmt.Printf("%T check: %v \n", check, check.IsValueValid(5))
}
}
}
[]CheckParamValid
切片可使用实现此接口的任意类来填充。
继承
go通过组合语法糖实现的继承,即在子类中直接嵌入父类(然后就可以直接访问子类的成员与方法):
- 多个相同基类时,不能使用匿名组合(只能定义不同的变量)
- 匿名组合初始化其字段名即为基类名(初始化时,要么全部带字段名,要么全部不带);
- 组名没有多态能力:如下Calc调用的Add永远是Base的(即使子类中重新定义了Add);若要Calc调用子类的Add,必须在子类中重新实现下Calc函数;
type Base struct {
Name string
Count int
}
func (this *Base)Output()string{
return fmt.Sprintf("name: %v, count: %v", this.Name, this.Count)
}
func (this *Base)Calc() {
this.Add()
}
func (this *Base)Add(){
this.Count += 1
}
type Derived struct {
Base
Score float32
}
func (this *Derived)Add(){
this.Count += 10
}
func DeriveTest(){
b := Base{
Name: "Base",
Count: 1,
}
d := Derived{
Base{"Derived",1},
10,
}
// d := Derived{
// Base: Base{Name: "explicit"},
// Score: 0,
// }
b.Add()
d.Add() // 调用的Derived的Add
fmt.Println(b.Output())
fmt.Println(d.Output())
b.Calc()
d.Calc() // 调用的Base的Add
fmt.Println(b.Output())
fmt.Println(d.Output())
}
// name: Base, count: 2
// name: Derived, count: 11
// name: Base, count: 3
// name: Derived, count: 12