go数据结构中的继承

时间:2019-07-10 07:36:29

标签: go

是否有更好的方法来实现继承? (在c#中,我们使用Abstract类和Interfaces实现类似的行为)。请参考以下代码以了解问题。

我尝试在Go中使用接口,但无法访问struct的数据字段。

type Vehicle struct {
    Id          int
    Name        string
    VehicleType VehicleTypeBase
}

type VehicleTypeBase struct {
    Id     int
    Name   string
    Milage int
}

type VehicleTypeSedan struct {
    VehicleTypeBase
    IsABSEnabled bool
}

type VehicleTypeHatchback struct {
    VehicleTypeBase
    Is4WheelDriveEnabled bool
}

func main() {
    var veh Vehicle

    veh = Vehicle{
        Id:   1,
        Name: "Zeep Compass",
        VehicleType: VehicleTypeSedan{
            Id:           1,
            Name:         "Sedan",
            Milage:       13,
            IsABSEnabled: true,
        },
    }
}

// Above initialization gives error. Here, I would like to understand that how // to achieve inheritance using base class
// in Golang. Is there a way to solve this situation in Go??

错误消息是:

  

。\ main.go:40:3:在字段值中不能使用VehicleTypeSedan文字(类型VehicleTypeSedan)作为VehicleTypeBase类型

2 个答案:

答案 0 :(得分:0)

结构嵌入是lang首选的方式。构想比继承更好。

https://golang.org/doc/effective_go.html#embedding

您应该为Vehicle声明一个接口,并且所有Vehicle都实现该接口。

这是设计级的问题,而不仅仅是解决错误。由于尚不清楚您将如何使用和处理车辆。我会做一些假设。

通过嵌入方式应将可重用结构嵌入特定结构中。

type VehicleTypeGeneral struct {
    Id     int
    Name   string
    Milage int
}

//Embed VehicleTypeGeneral
type VehicleTypeHatchback struct {
    VehicleTypeGeneral
    Is4WheelDriveEnabled bool
}

如果我们创建VehicleTypeHatchback的实例vh,那么我们可以访问VehicleTypeHatchback的字段以及VehicleTypeGeneralvh.Is4WheelDriveEnabled vh.VehicleTypeGeneral.Name

如果VehicleTypeGeneral实现的接口类似于Vehicle接口,那么VehicleTypeHatchback也会实现该接口。您可以通过实现这些方法来覆盖。

我在processSpecificVehicle函数中添加了类型检查示例。但是这些事情会减慢执行速度。而是尝试使用processVehicleprocessAbsVehicle

中提到的方法

接口也不应该有太多方法。一个或两个就足够了,否则违反了接口隔离原则。保持界面简短有意义,并根据界面使用者的需求进行设计。

完整的示例并带有以下假设:

package main
import "fmt"

type Vehicle interface {
    GetId() int
    GetName() string
}

type AbsVehicle interface {
    IsAbsEnabled() bool   
}

type VehicleTypeGeneral struct {
    Id     int
    Name   string
    Milage int
}

func (v *VehicleTypeGeneral) GetId() int{
    return v.Id
}

func (v *VehicleTypeGeneral) GetName() string{
    return v.Name
}

type VehicleTypeSedan struct {
    VehicleTypeGeneral
    IsABSEnabled bool
}

func(vs *VehicleTypeSedan) IsAbsEnabled() bool {
    return vs.IsABSEnabled
}

type VehicleTypeHatchback struct {
    VehicleTypeGeneral
    Is4WheelDriveEnabled bool
}

func main() {
    println("Hello")

    var vehicle = VehicleTypeSedan{IsABSEnabled: true, VehicleTypeGeneral: VehicleTypeGeneral{Id:1001,Name:"Sedan 1", Milage:12}}

    processVehicle(&vehicle)
    processAbsVehicle(&vehicle)
    processSpecificVehicle(&vehicle)
    processSedan(&vehicle)
}

func processVehicle(vehicle Vehicle){
    println(vehicle.GetId())
    println(vehicle.GetName())  
}


func processAbsVehicle(vehicle AbsVehicle){
    println(vehicle.IsAbsEnabled())

}

func processSpecificVehicle(vehicle Vehicle){
    switch v := vehicle.(type) {
    case *VehicleTypeSedan:
        fmt.Printf("Its a sedan %v with ABS %v ", v.GetName(), v.IsAbsEnabled())
    case *VehicleTypeHatchback:
        fmt.Printf("Its a VehicleTypeHatchback %v", v.GetName())
    default:
        fmt.Printf("Its a Vehicle")
    }

}

func processSedan(vs *VehicleTypeSedan){
    println("\nprocess sedan")
    println(vs.VehicleTypeGeneral.Name)
    println(vs.IsABSEnabled)
}

答案 1 :(得分:-1)

可以工作!

type Vehicle struct {                        
    Id          int
    Name        string
    VehicleType VehicleTypeInterface
}

type VehicleTypeInterface interface{}

type VehicleTypeBase struct {
    Id     int
    Name   string
    Milage int
}

type VehicleTypeSedan struct {
    VehicleTypeBase
    IsABSEnabled bool
}

type VehicleTypeHatchback struct {
    VehicleTypeBase
    Is4WheelDriveEnabled bool
}

func main() {
    var veh Vehicle

    veh = Vehicle{
        Id:   1,
        Name: "Zeep Compass",
        VehicleType: VehicleTypeSedan{
            VehicleTypeBase: VehicleTypeBase{
                Id:     3,
                Name:   "Sedan",
                Milage: 13,
            },
            IsABSEnabled: true,
        },
    }
    fmt.Printf("%+v", veh)
}