接口和将匿名字段嵌入结构体

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

Interfaces and embedding anonymous fields into structs

问题

我正在尝试表示一个戴眼镜的人靠近窗户时发生附近爆炸的情况。main是在爆炸期间应该完成的任务的草图。某些东西应该收集爆炸附近的物体列表,并为每个物体执行特定的操作(如破碎或融化)。玻璃和窗户如预期般破碎,但由于某种原因,人也破碎了。为什么?

package main
import "fmt"

type Human struct { Glasses }
type Glasses struct {}
type Shatterable interface { shatter() }

func (g Glasses) shatter() {}

type Window struct {}
func (w Window) shatter() {}

func main() {
    h := Human{Glasses{}}
    objectsInProximity := []interface{}{h,h.Glasses,Window{}}
    for _,o := range objectsInProximity {
        shatter(o)
    }
}

func shatter(i interface{}) {
    s, ok := i.(Shatterable)
    if ok {
        fmt.Printf("shattering a %T\n", s)
        s.shatter()
    }
}
$ go run a.go
shattering a main.Human
shattering a main.Glasses
shattering a main.Window
英文:

I'm trying to represent a human wearing glasses near a window when a nearby explosion occurs. main is a sketch of what should be done during the explosion. Something should gather up a list of objects in proximity of the explosion and do specific things (such as shattering or melting) for each of them. The glass and window shatter as expected, but for some reason the human also shatters. Why?

package main
import "fmt"
type Human struct { Glasses }
type Glasses struct {}
type Shatterable interface { shatter() }
func (g Glasses) shatter() {}
type Window struct {}
func (w Window) shatter() {}

func main() {
    h := Human{Glasses{}}
    objectsInProximity := []interface{}{h,h.Glasses,Window{}}
    for _,o := range objectsInProximity {
        shatter(o)
    }
}

func shatter(i interface{}) {
    s, ok := i.(Shatterable)
    if ok {
        fmt.Printf("shattering a %T\n", s)
        s.shatter()
    }
}

<!

$ go run a.go
shattering a main.Human
shattering a main.Glasses
shattering a main.Window

答案1

得分: 6

如在此讨论串中提到:

> 我们正在讨论结构体的匿名字段(http://golang.org/ref/spec#Struct_types)。

(修改版本,因为术语“超集”令人困惑)

具有匿名字段的结构体满足所有由匿名字段或结构体本身声明的接口方法

type Human struct { Glasses }

由于Glasses可以被打碎,Human也满足相同的接口。


注意:在结构体中嵌入匿名字段是最接近“继承”的方式,尽管对于“在Golang中,当你有多重继承时,接口的意义是什么”的回答提醒我们:

> Go没有继承。
如果Man通过将其作为匿名字段来“扩展”Human,任何使用Human作为参数的方法都无法将Man作为参数。

(这意味着在这里Human扩展了...Glasses?这可能显示了某种设计缺陷)

我在“如果结构体A嵌入在B中,A的方法可以访问B的方法和字段吗?”中解释过这不是真正的子类型化。

> 接口使函数能够具有可以接受不同结构体作为参数的“占位符”参数。

在这里,如果Human不应该被打碎,就不应该包含匿名字段Glasses

英文:

As mentioned in this thread:

> We're talking about anonymous fields of a struct
(http://golang.org/ref/spec#Struct_types).

(modified version, as the term superset is confusing)

A struct with an anonymous field satisfies every interface with all the interface methods declared by the anonymous field or the struct itself.

type Human struct { Glasses }

Since Glasses can be shattered, Human also satisfy the same interface.


Note: embedding anonymous field in a struct is the closest to "inheritance", even though the answer to "Golang: what's the point of interfaces when you have multiple inheritance" reminds us that:

> Go doesn't have inheritance.
If Man 'extended' Human (by having it as an anonymous field), any method that used Human as an argument, would not be able to take Man as an argument.

(That means here Human extends... Glasses?! That might show some kind of design imperfection)

I explained before in "If struct A is embedded in B, can methods on A access method and fields of B?" that this isn't true sub-typing.

> Interfaces enable functions to have a 'placeholder' parameter which can take different structs as an argument.

Here, if Human isn't supposed to be shattered, it shouldn't include the anonymous field Glasses.

huangapple
  • 本文由 发表于 2014年9月9日 01:44:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/25730074.html
匿名

发表评论

匿名网友

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

确定