Есть ли в Go наследование? Как достигается полиморфизм?

Ответ

В Go нет классического наследования, как в Java или C++. Вместо этого в Go используется принцип «композиция вместо наследования».

Повторное использование кода достигается через встраивание (embedding) структур, а полиморфизм — через интерфейсы.

Пример встраивания (композиции):

import "fmt"

type Animal struct {
    Name string
}

func (a *Animal) Speak() {
    fmt.Printf("%s издает звукn", a.Name)
}

type Dog struct {
    Animal // Встраивание типа Animal. Поля и методы Animal "поднимаются" на уровень Dog.
    Breed  string
}

func main() {
    d := Dog{
        Animal: Animal{Name: "Рекс"},
        Breed:  "Овчарка",
    }
    d.Speak() // Вызывается метод Speak() из встроенной структуры Animal
    fmt.Println(d.Name) // Поле Name также доступно напрямую
}

Ключевые моменты:


  1. Встраивание — не наследование: Это синтаксический сахар для композиции. Dog имеет Animal, а не является Animal. Это позволяет избежать хрупких иерархий наследования.



  2. Полиморфизм через интерфейсы: Полиморфизм в Go достигается неявно. Любая структура, реализующая все методы интерфейса, автоматически удовлетворяет этому интерфейсу. Это позволяет писать гибкий и слабосвязанный код.


// интерфейс, описывающий поведение
type Speaker interface {
    Speak()
}

// функция принимает любой тип, удовлетворяющий интерфейсу Speaker
func MakeSound(s Speaker) {
    s.Speak()
}