Composition Instead of Inheritance

Composition Instead of Inheritance

In this tutorial, we will discuss how we can use composition instead of inheritance in the Go language. Go language does not support inheritance. However, it does support composition. The generic definition of composition is “put together”.

Composition Instead of Inheritance

One example of composition is a car. A car is composed of wheels, an engine and various other parts.

We can achieve the composition 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 an author struct with fields firstName, lastName and bio. We have also added a method fullName() with the author as receiver type, which returns the author’s full name.

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 the post struct is composed of an author.

Now post struct has to access all the fields and methods of the author struct. We have also added details() method to the post struct, which prints the author’s title, content, fullName and bio.

Whenever one struct field is embedded in another, Go language allows us 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

Run in playground

Composition Instead of Inheritance
Scroll to top