Go支持继承吗?

时间:2013-07-31 13:57:13

标签: go

我听过很多人谈论Go,以及它如何不支持继承。在实际使用这种语言之前,我只是跟人群一起听了听。在用语言搞砸了之后,掌握了基础知识。我遇到了这种情况:

    package main

type Thing struct {
    Name string
    Age  int
}

type UglyPerson struct {
    Person
    WonkyTeeth bool
}

type Person struct {
    Thing
}

type Cat struct {
    Thing
}


func (this *Cat) SetAge(age int){
    this.Thing.SetAge(age)
}

func (this *Cat GetAge(){
     return this.Thing.GetAge() * 7
}

func (this *UglyPerson) GetWonkyTeeth() bool {
    return this.WonkyTeeth
}

func (this *UglyPerson) SetWonkyTeeth(wonkyTeeth bool) {
    this.WonkyTeeth = wonkyTeeth
}

func (this *Thing) GetAge() int {
    return this.Age
}

func (this *Thing) GetName() string {
    return this.Name
}

func (this *Thing) SetAge(age int) {
    this.Age = age
}

func (this *Thing) SetName(name string) {
    this.Name = name
}

现在,它由Thing Struct构成了Person和Cat Structs。通过这样做,Person和Cat结构不仅与Thing Struct共享相同的Fields,而且通过组合,Thing的方法也被共享。这不是继承吗?同样通过实现这样的接口:

type thing interface {
    GetName() string
    SetName(name string)
    SetAge(age int)
}

所有三个Structs现在都加入了或者我应该说,可以以同质的方式使用,例如一系列“东西”。

所以,我把它放在你身上,这不是继承吗?

修改

添加了一个名为“Ugly person”的新派生结构,并覆盖了Cat的SetAge方法。

3 个答案:

答案 0 :(得分:4)

它是继承,但可能不是你可能会继承的那种继承。您的示例看起来很有希望b / c PersonCat在行为上和结构上彼此相等,以模型名称为模。

只要您尝试使用此“继承”来“扩展”某些基类型,例如添加字段,您就会发现“基类”的接收者始终是基类,从不扩展的。 IOW,你无法实现结构上的多态类型层次结构。

OTOH,Go通过接口支持纯粹的行为继承。将一个接口嵌入到另一个会创建一个继承树。

package main

import "fmt"

type Thing struct {
    Name string
    Age  int
}

func (t *Thing) me() {
    fmt.Printf("I am a %T.\n", t)
}

type Person struct {
    Thing
}

func (p *Person) Iam() {
    fmt.Printf("I am a %T.\n", p)
}

type Cat struct {
    Thing
}

func (c *Cat) Iam() {
    fmt.Printf("I am a %T.\n", c)
}

func main() {
    var p Person
    var c Cat

    p.me()
    p.Iam()

    c.me()
    c.Iam()
}

答案 1 :(得分:2)

这叫做作曲。人或猫的方法无法直接进入Thing的领域。如果是Cat实现了一个自己的SetAge(),你想要调用Thing,你必须调用myCat.Thing.SetAge(42)而不是myCat.SetAge(42)。

答案 2 :(得分:1)

既然您提到了C#,请尝试在go中执行此操作。在Go中不能使方法调用成为虚拟(除了通过接口)。

// this is C#, not go
public class Thing 
{
    public virtual string Name {get; set;}
    public virtual int Age {get; set;}
}

public class Person : Thing {}
public class Cat : Thing 
{
    public override int Age 
    {
        get
        {
            return base.Age * 7; //age in cat's years
        }
    }
}

并像这样调用它:

Thing t = new Cat() {Name="Tom", Age=5}; // a Cat object is assigned 
                                         // to a Thing variable
Console.WriteLine(t.Age); // outputs 35. 
                          // t.Age refers to Cat's implementation 
                          // of Age, not Thing's. Notice how Age is virtual 
                          // in Thing and overridden in Cat