More meth(odes) please!
We have learned how to write methods in Go, that they can be seen as functions with an implicit first parameter that is its receiver, and we saw some facilities that Go offers when working with pointers and receivers.
In this chapter we will see how to implement some OOP concepts using methods. It will be fun and relatively easy.
Structs with anonymous fields
I didn't tell you about this when we studied
structs, but we actually can
declare fields without specifying names for them (just the type). It is for
this reason that we call them anonymous fields (the lack of a name).
When an anonymous field is a
struct its fields are inserted (embedded)
into the struct containing it.
Let's see an example to help clarify this concept:
On line 29 and 33 we were able to access and change the fields
weight just as if they were declared as fields of the
This is because fields of
Human are embedded in the struct
Cool, isn't it? But there's more than this interpolation of fields, an anonymous field can be used with its type as its name!
This means that
Student has a field named
Human that can be used as
regular field with this name.
Anonymous fields of any type
Accessing, and changing an anonymous field by name is quite useful for
anonymous fields that are not
structs. * -- Who told you that anonymous
fields must be*
structs?! * -- I didn't!*
In fact, any named type and pointers to named types are completely acceptable.
Let's see some anonymous action:
The anonymous field mechanism lets us inherit some (or even all) of the implementation of a given type from another type or types.
Anonymous fields conflicts
What happens if
Human has a field
Student has also a field
with the same name?
This kind of conflicts are solved in Go simply by saying that the outer name
hides the inner one. i.e. when accessing
phone you are working with
This provides a way to override a field that is present in the "inherited" anonymous field by the one that we explicitely specify in our type.
If you still need to access the anonymous one, you'll have to use the type's name syntax:
Great! So now you ask,
"Now, what does all this have to do with methods?"
Attaboy, you didn't forget the main subject of the chapter. Kudos.
Methods on anonymous fields
The good surprise is that methods behave exactly like anonymous fields. If an anonymous field implements a given method, this method will be available for the type that is using this anonymous field.
Human type implements a method
SayHi() that prints a greeting,
this same method is available for both
Employee! You won't
need to write it twice for them:
Think about it: you often need to represent things that share some attributes or characteristics, this is solved with the anonymous field mechanism. And when you need to represent a shared behavior or functionality, you can use a method on an anonymous field.
Overriding a method
What if you want the
Employee to tell you where he works as well?
Easy, the same rule for overriding fields on conflicts applies for methods,
and we happily exploit this fact:
And... It worked like a charm!
With these simple concepts, you can now design shorter, nicer and expressive programs. In the next chapter we will learn how to enhance this experience even more with a new notion: Interfaces.