在Go语言中,可以通过将基类的实例赋值给继承类来实现继承。

huangapple go评论94阅读模式
英文:

Assignment from base class to inherit class in Go

问题

我知道Go语言没有这样的面向对象概念,但是让我借用一下它们只是为了更容易解释。面向对象的继承允许将行为泛化到更抽象的类型或类中,使用一个类和它的子类,子类继承了父类的所有成员字段和行为。Go语言没有这样的概念,但是可以通过相同的范式实现,文章中解释了Go语言中的继承和子类化。

我的问题更多是关于赋值。假设我有一个"基类"Vehicle和一个"继承类"Car,如下所示:

type Vehicle struct {
    wheelCount int
}

type Car struct {
    Vehicle //匿名字段Vehicle
    Maker   string
}

在真正的面向对象编程中,我可以将一个Vehicle对象赋值给一个Car对象,但是我还没有找到在Go语言中实现这个的方法。所以我的问题是,

  • 是否有可能这样做?
  • 如果不行,那么在Go语言中如何从一个"Vehicle"写一个"Car"的构造函数?我知道规范的方式是c := Car{Vehicle{4}, "Ford"},但是如果我在Car中有其他成员字段,比如Module等,我只想初始化Vehicle的成员字段,不想初始化其他的字段,该怎么办?

我已经为你准备了一些初始代码,你可以在这里开始:http://play.golang.org/p/dcs9r7vPjZ

谢谢!

英文:

I know Go doesn't have such OO concept, but let me borrow them just to make it easier to explain.

OO inherits allows generalizing behavior to a more abstract type or class, using a class and a subclass of it, where the subclass inherits all the member fields and behaviors of the parent class. Go doesn't have such concept, but can achieve the same paradigm, in which the article explains Inheritance and subclassing in Go.

My question is more on the assignment. Suppose I have a "base class" Vehicle and a "inherit class" Car, like the following:

type Vehicle struct {
    wheelCount int
}

type Car struct {
    Vehicle //anonymous field Vehicle
    Maker   string
}

In true OO, I can assign a Vehicle object into a Car object, but I haven't found a way to do that in Go. So my questions are,

  • Is it possible to do that?
  • Else, what's the Go way to write a "Car" constructor from a "Vehicle"? I know the canonical way is c := Car{Vehicle{4}, "Ford"}, but what if I have other member fields in Car, like Module etc, and I'd like only to initial the member fields from Vehicle, nothing else?

I've prepared something for you to start with,
http://play.golang.org/p/dcs9r7vPjZ

Thanks

答案1

得分: 4

我可以将一个 Vehicle 对象分配给一个 Car 对象吗?

你是不是指相反的情况?在面向对象编程中,你不能将 Vehicle 分配给 Car,但你可以将 Car 或 Van 分配给 Vehicle。

如果是这样,当然可以在 Go 中实现:

var v Vehicle
c := Car{Vehicle: Vehicle{1}}
v = c.Vehicle
fmt.Println(v) // 输出 {1}

这个示例还演示了你可以精确初始化你想要的字段。然而,这种类型的对象构造方法相当有限,所以通常使用构造函数来实现类似构造器的行为:

func CreateVehicle(wheels int) Vehicle {
    return Vehicle{wheels}
}

func CreateCar(wheels int, maker string) Car {
    return Car{CreateVehicle(wheels), maker}
}

func main() {
    var v Vehicle
    c := CreateCar(4, "Ford")
    v = c.Vehicle
    fmt.Println(v)
}

顺便说一下,在 Go 中管理引用可能会比较棘手,如果你通常使用引用类型。结构体始终按值传递。要通过引用传递,使用 & 获取引用,使用 * 指定按引用传递的参数。

所以,这样是行不通的:

func (v Vehicle) SetNumberOfWeels(wheels int) {
    v.wheelCount = wheels
}

func main() {
    v := Vehicle{}
    v.SetNumberOfWeels(5)
    fmt.Println(v) // 输出 {0}
}

但这样是可以的:

func (v *Vehicle) SetNumberOfWeels(wheels int) {
    v.wheelCount = wheels
}

func main() {
    v := Vehicle{}
    v.SetNumberOfWeels(5)
    fmt.Println(v) // 输出 {5}
}
英文:

> I can assign a Vehicle object into a Car object

Do you mean opposite? In OOP you cannot assign Vehicle to Car, but you can assign either Car or Van to Vehicle.

If so, you can do this in Go, of course:

var v Vehicle
c := Car{Vehicle:Vehicle{1}}
v = c.Vehicle
fmt.Println(v) // prints {1}

This example also demonstrates that you can initialise exactly the fields you want to. However, this type of object construction is quite limited so the construction method is what typically used to get constructor-like behaviour:

func CreateVehicle(wheels int) Vehicle {
    return Vehicle{wheels}
}

func CreateCar(wheels int, maker string) Car {
    return Car{CreateVehicle(wheels), maker}
}

func main() {
    var v Vehicle
    c := CreateCar(4, "Ford")
    v = c.Vehicle
    fmt.Println(v)
}

BTW, the reference management can be tricky in Go if you normally work with reference types. The structs are always passed by value. To pass it by reference, use & to get reference and * to specify the byref parameter.

So, this will not work:

func (v Vehicle) SetNumberOfWeels(wheels int) {
    v.wheelCount = wheels
}

func main() {
    v := Vehicle{}
    v.SetNumberOfWeels(5)
    fmt.Println(v) // prints {0}
}

But this will:

func (v *Vehicle) SetNumberOfWeels(wheels int) {
    v.wheelCount = wheels
}

func main() {
    v := Vehicle{}
    v.SetNumberOfWeels(5)
    fmt.Println(v) // prints {5}
}

huangapple
  • 本文由 发表于 2015年7月28日 09:04:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/31665810.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定