TL ; DR:
Go has no classes or super. Puppy embeds a Dog, and when Puppy defines its own bark it hides the embedded one. The embedded Dog is still there as this.Dog, so this.Dog.bark() runs the parent's version. This lets you extend the parent's behavior instead of replacing it.
func (this Puppy) bark() {
this.Dog.bark() // do everything the parent did
fmt.Printf("Yip! Said %s\n", this.name)
}
Why it matters
Overriding a method replaces the parent's behavior. Often you want to extend it instead: keep what the parent did and add something more. A typical example is a save method: the parent writes the row to the database, and a subclass runs the parent's save first and then writes a log line.
Your task
Dog (with its bark method), Puppy (which embeds Dog) and the constructor NewPuppy are written. You write the bark method of Puppy: func (this Puppy) bark(). Inside it:
- call the embedded parent's version with
this.Dog.bark(), soWoof! I am <name>still prints; - then
fmt.Printf("Yip! Said %s\n", this.name).
Notes:
Puppyis declared asstruct { Dog }(embedding).NewPuppy(name)builds it and is already written.this.nameworks because the embeddedDog's fields are promoted toPuppy.
The driver (already written, it runs when you press Run):
buddy := NewPuppy("Buddy")
buddy.bark()
rex := NewPuppy("Rex")
rex.bark()
dog := Dog{name: "Max"}
dog.bark()
buddyis aPuppy: itsbarkprints the parent's line, then its own.rexis anotherPuppy: the names come from the object, nothing is hard-coded.dogis a plainDog: itsbarkis unchanged and prints only the parent's line, with noYip!.
Expected output:
Woof! I am Buddy
Yip! Said Buddy
Woof! I am Rex
Yip! Said Rex
Woof! I am Max
Free plan: 30 tutor messages. Premium is unlimited.
