Go支持继承吗?

Go支持继承吗?,go,Go,我听过很多人谈论Go,以及它如何不支持继承。在真正使用这种语言之前,我只是随大流,听听众说。在稍微弄乱了一下语言之后,开始掌握基本知识。我遇到了这样的情况: package main type Thing struct { Name string Age int } type UglyPerson struct { Person WonkyTeeth bool } type Person struct { Thing } type Cat

我听过很多人谈论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
}
现在,这是什么,它组成了Person和Cat结构,来自Thing结构。通过这样做,不仅Person和Cat结构与Thing结构共享相同的字段,而且通过组合,Thing的方法也共享。这不是遗产吗?此外,通过实现这样的接口:

type thing interface {
    GetName() string
    SetName(name string)
    SetAge(age int)
}
所有三个结构现在都被连接起来了,或者我应该说,可以以同质的方式使用,比如一个“thing”数组

所以,我把它推给你,这不是遗产吗

编辑


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

这是继承,但可能不是你想要的那种继承。您的示例看起来很有希望b/c
Person
Cat
在行为上和结构上按类型名相互相等

只要您尝试使用这个“继承”来“扩展”一些基类,例如添加字段,您就会发现“基类”的接收者总是基类,而不是扩展的基类。照此看来,您无法实现结构上的多形类型层次结构

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()
}

这叫作文。人或猫的方法无法直接访问事物的领域。另外,如果Cat实现了一个自己的SetAge(),并且您想调用Thing中的一个,那么您必须调用myCat.Thing.SetAge(42)而不是myCat.SetAge(42)。

既然您提到了C#,请尝试在go中这样做。方法调用不能在Go中进行虚拟(通过接口除外)

//这是C#,不是go
公共类事物
{
公共虚拟字符串名称{get;set;}
公共虚拟整数{get;set;}
}
公共类人物:东西{}
公共类猫:东西
{
公共覆盖int Age
{
得到
{
return base.Age*7;//猫的年龄
}
}
}
这样称呼它:


在C#这样的语言中,普通继承不存在这个问题吗?因此调用base.something()或重写方法来隐藏基?如果我不想重写,为什么要在Cat中实现设置?我仍然可以在Cat SetAge方法中调用SetAge方法?使用受保护的字段,您可以直接在派生类的方法中访问它们。在这里,您必须为这些字段创建公共访问器方法,即使您不想将它们公开。我只是以SetAge()方法为例。但是考虑到逻辑上的任何其他方法。您没有隐藏父类型的方法,它是可调用的,如上所示。不,正如您所说,它不是继承而是组合。学究气…你怎么说?人是物还是人有物?你不能传递一件东西而不是一个人。关于接口是的,这是某种继承,但不能继承实现的行为,只能继承它们的定义。想象一下,一个人可以做一些事情(但每个实现者都必须以自己的方式来做)。但是语法糖让它感觉像是继承,这难道不是使用OO语言时继承的全部内容吗?我想说,共享一件事情的特征。我不知道,我认为这种构图形式与普通的物体构图有点不同。创建系统时,很明显,一个对象由许多对象组成。但是go中的语法糖会给出Cat和Person GetName()。但是合成/继承不是语法糖,它们是不同的行为!你能用我上面的愚蠢代码举例说明你说的话吗?只是为了让我完全理解。我不知道,加上ShoeSize:)+1,对,但看看原来的问题,我不想打败那个OP,我明白你们的意思……我通过添加一个新的结构,叫做“丑人”,并给他一个“怪牙”,扩展了这个人。“到目前为止,我还没有发现问题?”WeNeedAnswers:我不确定我是否做了一个好的例子,但请看一看问题的关键是,“基类”不知道它是否单独存在或嵌入到任何子类型中。
Thing
的方法所看到的只是
Thing
。如果子类型重写了Thing的方法,那么在Thing中仍然会调用未重写的方法。我理解。谢谢。检查我上面的代码…我在Go中添加了一个覆盖…对覆盖没有多大作用…但是它做了些什么。区别不是覆盖本身。这取决于如何调用它(以及如何将虚拟调用解析为变量包含的实际派生类型)。如果我有时间,我会尝试在GoYou中添加一个反例来讨论共享内存空间?是的,Go中的构造函数是另一个:)
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