golang - 面向对象继承 下篇

656 阅读3分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

同一个结构体继承了多个不同的结构体

多个不同结构体有相同字段时,如何使用?

model包,新建payment_other.go文件, 这里我们将结构体paymentOther,结构体内容同PaymentArgs相同,payment_other.go的内容

package model
// 微信支付
// 支付宝
// 银联
// 银行卡
type PaymentOther struct {
    AppID string
    MchID string
    Key string
    CallbackUrl string
}

这里我们让Alipay这个结构体同时继承PaymentArgsPaymentOther, Alipay.go的内容

package model
import "fmt"
type Alipay struct {
    PaymentArgs  // 匿名结构体
    PaymentOther PaymentOther // 有名结构体
    AlipayOpenID string
    string
}

这里Alipay结构体想访问AppID字段就必须指定结构体名,这里有两个概念匿名结构体有名结构体

匿名结构体 在嵌套结构体时没有指定结构体变量名,例如上面Alipay结构体中的PaymentArgs
有名结构体 在嵌套结构体时没有指定结构体变量名,例如上面Alipay结构体中的PaymentOther
因为他们具有相同的字段,如果想访问Alipay结构体中的AppID就必须指定结构体变量名或者匿名结构体名

main.go中,如下的访问

fmt.Println(alipay.PaymentOther.AppID)
fmt.Println(alipay.PaymentArgs.AppID)

方法的继承与重载

我们为payment.go文件中PaymentArgs结构体增加方法

func (this *PaymentArgs)Info() {
    fmt.Printf("Info = %v\n",this)
}

这样我们定义的Alipay结构体与WeixinPay结构体自动就继承了PaymentArgs的方法
我们在main.go中调用

paymentArgs := model.PaymentArgs{
    AppID:       "superAppid",
    MchID:       "superMchid",
    Key:         "superKey",
    CallbackUrl: "https://api.luboke.com/super",
}
paymentArgs.Info()

同样的我们可以对继承的方法进行重定义
在我们的Alipay.go中为Alipay结构体增加方法

func (this *Alipay)Info()  {
    fmt.Printf("alipay = %v\n",this)
}

此时Alipay结构体重写了Info()方法,在main.go中调用

alipay := &model.Alipay{
    PaymentArgs:  model.PaymentArgs{
        AppID:"alipay123",
        MchID:"alipaymchid",
        Key:"alipayfjkadsfjkasfjas",
        CallbackUrl:"https://api.luboke.com/alipay",
    },
    AlipayOpenID: "alipayopenid",
}
alipay.Info()

结构体继承访问流程

这里以上面Alipay结构体当中访问AppID为例
1.先判断AppID是否属于Alipay,如果有就访问
2.如果没有,继续去找他继承的结构体PaymentArgs,如果有就访问
3.如果没有继续去找PaymentArgs这个结构的所继承的结构体,如果有就访问,没有就报错,因为PaymentArgs结构体没有再继承别的结构体

结构体注意事项

1.如果一个结构中继承了多个结构体,而这些多个结构体当中有相同的字段,那么我们就需要使用 结构体名来访问

如上面我们所演示的访问Alipay结构体中的AppID就必须指定结构体变量名或者匿名结构体名

2.一个内置类型可以做为结构体的匿名字段,这种方式只能在本包访问

//定义一个结构体,字段为一个内置string类型
type StringStruct struct {
    string
}

ss := StringStruct{"hello"}
//这种方式只能在本包中访问
fmt.Println(ss.string)

继承有什么优点

1.提高代码的复用率
2.提高代码的扩展性与维护性