2

我听过很多人谈论 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 结构组成了 Person 和 Cat 结构。这样,不仅 Person 和 Cat 结构体与 Thing 结构体共享相同的 Fields,而且通过组合,Thing 的方法也被共享。这不是继承吗?同样通过实现这样的接口:

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

所有三个结构现在都连接了,或者我应该说,可以以同质的方式使用,例如“事物”的数组。

所以,我推给你,这不是继承吗?

编辑

添加了一个新的派生结构,称为“丑陋的人”,并为 Cat 覆盖了 SetAge 方法。

4

3 回答 3

4

它是继承,但可能不是您可能追求的那种继承。您的示例看起来很有希望 b/cPerson并且Cat在行为和结构上彼此模数类型名称相同。

一旦您尝试使用此“继承”来“扩展”某些基类型,例如添加字段,您会发现“基类”的接收者始终是基类,而不是扩展的. 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()
}
于 2013-07-31T14:10:05.133 回答
2

这叫作曲。Person 或 Cat 的方法不能直接访问 Thing 的字段。此外,如果例如 Cat 实现了自己的 SetAge(),并且您想调用其中的一个,则必须调用 myCat.Thing.SetAge(42) 而不是 myCat.SetAge(42)。

于 2013-07-31T14:12:11.480 回答
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
于 2013-07-31T14:32:02.377 回答