Home  >  Article  >  Backend Development  >  Composition Over Inheritance in Go

Composition Over Inheritance in Go

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-10-30 12:24:02360browse

Composition Over Inheritance in Go

When designing software, the "composition over inheritance" principle often leads to more flexible, maintainable code. Go, with its unique approach to object-oriented design, leans heavily into composition rather than inheritance. Let's see why.

Why Go Prefers Composition

In traditional OOP languages, inheritance lets one class inherit behaviors and properties from another, but this can lead to rigid, hard-to-change hierarchies. Go avoids inheritance altogether and instead encourages composition—where types are built by combining smaller, focused components.

Composition in Action

Imagine we’re modeling a company with different types of workers: some are engineers, some are managers, and some are interns. Instead of creating a complex class hierarchy, we’ll define specific behaviors as independent types and then compose them.

Example: Worker Behaviors in Go

package main

import "fmt"

type Worker interface {
    Work()
}

type Payable struct {
    Salary int
}

func (p Payable) GetSalary() int {
    return p.Salary
}

type Manageable struct{}

func (m Manageable) Manage() {
    fmt.Println("Managing team")
}

type Engineer struct {
    Payable
}

func (e Engineer) Work() {
    fmt.Println("Engineering work being done")
}

type Manager struct {
    Payable
    Manageable
}

func (m Manager) Work() {
    fmt.Println("Managerial work being done")
}

Here:

  • Engineer and Manager embed Payable, giving them a Salary.
  • Manager also embeds Manageable, giving them team management abilities.
  • Each type implements Work() individually, satisfying the Worker interface.

Benefits of Composition

  • Simplicity: Each behavior is encapsulated in its struct, making it easy to extend.
  • Flexibility: New types or behaviors can be added without breaking existing code.
  • Reusability: Behaviors are modular, so we can easily combine them in different ways.

Using Interfaces with Composition

In Go, interfaces and composition work together to allow polymorphism without inheritance. Here’s how we can handle multiple worker types with a single function:

func DescribeWorker(w Worker) {
    w.Work()
}

func main() {
    engineer := Engineer{Payable{Salary: 80000}}
    manager := Manager{Payable{Salary: 100000}, Manageable{}}
    DescribeWorker(engineer)
    DescribeWorker(manager)
}

Go’s preference for composition over inheritance isn’t just a language quirk—it encourages cleaner, more modular code that’s adaptable to change. Instead of rigid hierarchies, you get flexible, reusable components that keep your codebase nimble and easy to maintain.

The above is the detailed content of Composition Over Inheritance in Go. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn