Composition Instead of Inheritance
In this tutorial, we are going to discuss about how we can use composition instead of inheritance in Go language.
Go language does not support inheritance, however it does support composition. The generic definition of composition is “put together”.
One example of composition is a car. A car is composed of wheels, engine and various other parts.
Composition can be achieved in Go language is by embedding one struct type into another.
A blog post is a perfect example of composition. Each blog post has a title, content and author information. This can be perfectly represented using composition.
Lets stop the theory and write some code right away π
package main
import (
"fmt"
)
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
In the above program, we have created a author
struct with fields firstName
, lastName
and bio
. We have also added a method fullName()
with the author
as receiver type and this returns the full name of the author.
The next step would be to create the post
struct.
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.author.fullName())
fmt.Println("Bio: ", p.author.bio)
}
In the above program, the post struct has fields title, content. It also has an embedded anonymous field author. This field denotes that post struct is composed of author.
Now post struct has access to all the fields and methods of the author struct. We have also added details() method to the post struct which prints the title, content, fullName and bio of the author.
Whenever one struct field is embedded in another, Go language gives us the option to access the embedded fields as if they were part of the outer struct.
This means that p.author.fullName()
in the above code can be replaced with p.fullName()
. Hence the details()
method can be rewritten as below,
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
Now that we have the author
and the post
structs ready.
package main
import "fmt"
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
func main() {
author := author{
"Ashok Kumar",
"Mariyala",
"Tech Learner",
}
post := post{
"Inheritance in Go",
"Go supports composition instead of inheritance",
author,
}
post.details()
}
Output
Title: Inheritance in Go
Content: Go supports composition instead of inheritance Author: Ashok Kumar Mariyala
Bio: Tech Learner