英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论