Sobes.tech
Junior

How is inheritance implemented in Golang?

sobes.tech AI

Answer from AI

Go does not have traditional class inheritance like in Java or C++. Instead, it uses two mechanisms:

  1. Embedding:

    • Embedding allows one struct or type to be embedded into another.
    • The embedded type "passes" its fields and methods to the embedding type.
    • Access to the fields and methods of the embedded type is direct, as if they were defined in the embedding type.
    • This mimics composition but with a more convenient syntax similar to inheritance.
    package main
    
    import "fmt"
    
    type Engine struct {
        Type string
    }
    
    func (e Engine) Start() {
        fmt.Println(e.Type, "engine started")
    }
    
    type Car struct {
        Engine // Embedding the Engine struct
        Model  string
    }
    
    func main() {
        car := Car{
            Engine: Engine{Type: "V8"},
            Model:  "Mustang",
        }
    
        // Direct access to the embedded struct's fields and methods
        fmt.Println("Car model:", car.Model)
        car.Start() // Calling the embedded struct's method
    }
    
  2. Interfaces:

    • Interfaces define a set of methods that a type must implement.
    • They define "behavior," not data structure.
    • A type does not need to explicitly declare that it implements an interface; it just needs to implement all the methods defined in the interface.
    • Interfaces provide polymorphism.
    package main
    
    import "fmt"
    
    type Speaker interface {
        Speak()
    }
    
    type Dog struct {
        Name string
    }
    
    func (d Dog) Speak() {
        fmt.Println(d.Name, "says Woof!")
    }
    
    type Cat struct {
        Name string
    }
    
    func (c Cat) Speak() {
        fmt.Println(c.Name, "says Meow!")
    }
    
    func main() {
        animals := []Speaker{
            Dog{Name: "Buddy"},
            Cat{Name: "Whiskers"},
        }
    
        for _, animal := range animals {
            animal.Speak() // Polymorphic call to Speak
        }
    }
    

The combination of embedding and interfaces allows Go to achieve flexibility and code reuse without the complexities and issues associated with traditional inheritance (e.g., the "diamond problem"). In Go, preference is given to composition and interfaces over inheritance hierarchies.