1

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
kostix
  • 51,517
  • 14
  • 93
  • 176
Dog
  • 7,707
  • 8
  • 40
  • 74
  • If you don't want `Human` to have a `Shatter` method, do `type Human struct { Glasses Glasses }`. Easier to just think of embedding (and, for that matter, inheritance) in mechanical terms (they do X, Y, and Z to the exposed API) rather than what they're like in human language. – twotwotwo Sep 08 '14 at 18:25
  • This question brightened my day to an unbelievable extent thank you @dog – ngood97 Oct 08 '21 at 23:34

1 Answers1

6

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.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Doesn't "A struct with an anonymous field satisfies every interface which is a superset of the methods of the anonymous field" mean if `A` has no methods, then `struct{A}` would implement every interface, since every interface is a superset of the empty set? And if `B` has one method `BM`, then `struct{B}` would implement every interface that has `BM` as one of its methods? And if `C` has two methods, `CM1` and `CM2`, `struct{C}` would not implement `interface{CM1,M}`, since that's not a superset of `{CM1,CM2}`? – Dog Sep 08 '14 at 20:15
  • @Dog No: to satisfy an interface, you have to implement *all* its methods. Which is why all struct satify the empty interface. – VonC Sep 08 '14 at 20:16
  • I know that's how normal interfaces work, but that thing you pasted is implying (AFAICT) something completely different (pretty much the opposite of how normal interfaces work) for anonymous fields. – Dog Sep 08 '14 at 20:20
  • @Dog superset might not be the best term, but all the methods of the interface are in Glasses + Human (actually, here only in Glasses): the **point of the answer**: the method of the anonymous field + the ones of the main class can respect an interface. Hence Human shatter. – VonC Sep 08 '14 at 20:22
  • @Dog I tried to edit the answer and revisit the quote, but the spirit of the answer stays: if the anonymous field respects an interface, by extension, the embedding struct respects it too: Human are Shatterable. – VonC Sep 08 '14 at 20:26
  • I see, so structs just inherit the methods from any anonymous structs they have. I thought `struct{A}` was just syntactic sugar for `struct{A A}`, which is why I asked [this other question](http://stackoverflow.com/questions/25515653/what-is-the-difference-between-structint-and-structint-int). – Dog Sep 08 '14 at 20:30
  • @Dog yes, although "inherit" isn't the best term, as I mentioned in http://stackoverflow.com/a/25664833/6309. – VonC Sep 08 '14 at 20:31
  • @Dog Saw you asked a few questions about stuff like this; the sections of the [spec](http://golang.org/ref/spec) touching on types and embedding (search for 'embed') and maybe interfaces might help. It's surprisingly readable, for a language spec. – twotwotwo Sep 08 '14 at 21:24