Go "inheritance" - the use of an anonymous type in the structure as a parameter of the method

I am trying to reinforce the concept of inheritance that Go offers (rather, "composition" than pure inheritance). However, I do not understand why I cannot use the "parent" type as a func parameter to create a generic function that acts on the parameter.

 package main import "log" type Animal struct { Colour string Name string } type Dog struct { Animal } func PrintColour(a *Animal) { log.Printf("%s\n", a.Colour) } func main () { a := new (Animal) a.Colour = "Void" d := new (Dog) d.Colour = "Black" PrintColour(a) PrintColour(d) } 

Assuming my understanding is wrong, how can I achieve what I want in Go?

Edit Note:

  • I don't want to bind behavior to a structure

  • I would like to keep the pointer type as a parameter of the method, because I work separately in the project for pets, and for this I need to manipulate the transferred structure before it acts on it.

  • In fact, my Dog structure would have extra fields / members; hope it doesn't pollute the water further

+8
inheritance go
source share
5 answers

I like the answers here so far, and I want to add one that allows you to do static type checking on the interface that you pass using the interface:

 package main import ( "fmt" ) type Animalizer interface { GetColour() string } type Animal struct { Colour string Name string } type Dog struct { Animal } func (a *Animal) GetColour() string { return a.Colour } func PrintColour(a Animalizer) { fmt.Print(a.GetColour()) } func main() { a := new(Animal) a.Colour = "Void" d := new(Dog) d.Colour = "Black" PrintColour(a) PrintColour(d) } 

On the playground

You can add additional fields to Dog . The difference with Uriel Answer is that PrintColour calls PrintColour not be executed at compile time if something else is passed than the implementation of struct Animalizer .

In addition, you will not need to use typwitch, as the compiler knows that Animalizer implements GetColour .

And finally, the behavior (printing) is separated from the structure, GetColour simply returns the color.

+11
source share

If you declare a PrintColour method of type Animal , it will be "inherited" if you include Animal in Dog .

This is called "Embedding" in the world of Go. See Attachment in the Effective Path section for more information.

Try something like:

 package main import "log" type Animal struct { Colour string Name string } type Dog struct { Animal } func (a *Animal) PrintColour() { log.Printf("%s\n", a.Colour) } func main () { a := new (Animal) a.Colour = "Void" d := new (Dog) d.Colour = "Black" a.PrintColour() d.PrintColour() } 

It produces:

2009/11/10 23:00:00 Void
2009/11/10 23:00:00 Black

Playground

+4
source share

You can try using interface{}

 package main import ("fmt" "reflect") type Animal struct { Colour string Name string } type Dog struct { Animal } func PrintColour(a interface{}) { switch a.(type){ case *Dog: fmt.Printf("Dog %s\n", a.(*Dog).Colour) case *Animal: fmt.Printf("Aimal %s\n", a.(*Animal).Colour) default: fmt.Printf("hmm %s\n", reflect.TypeOf(a)) } } func main () { a := new (Animal) a.Colour = "Void" d := new (Dog) d.Colour = "Black" PrintColour(a) PrintColour(d) } 
+3
source share

A nested (anonymous) field can be explicitly accessed using its name:

 package main import "log" type Animal struct { Colour string Name string } type Dog struct { Animal } func PrintColour(a *Animal) { log.Printf("%s\n", a.Colour) } func main() { a := new(Animal) a.Colour = "Void" PrintColour(a) d := new(Dog) d.Colour = "Black" // you can access the underlying "Animal" through "d.Animal" PrintColour(&d.Animal) } 

playground

In the link : the sentence after the second block of code explains how you can declare an “anonymous” field and it states:

An unqualified type name acts as a field name.

+1
source share

My example may not be very good, but you can do what you want:

http://play.golang.org/p/JoAlOvJthr

Essentially, use the interface to define the general functionality that you want to open to the outside world for all of your types and built-in types.

(My example may not be the best, but it works)

+1
source share

All Articles