Composition Instead of Inheritance

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

Run in playground

Composition Instead of Inheritance


Scroll to top