Сделать интерфейс для вычисления площади круга и квадрата, реализовать их в структурах cicle и square.go-42

В этом примере мы создадим интерфейс для вычисления площади и реализуем его для двух конкретных фигур - круга и квадрата.

Определение интерфейса

Сначала создадим интерфейс Shape, который будет требовать метод Area():

type Shape interface {
    Area() float64
}

Этот интерфейс:

  1. Называется Shape (фигура)
  2. Требует один метод Area(), который возвращает float64
  3. Любой тип, реализующий этот метод, автоматически удовлетворяет интерфейсу

Реализация для круга

Создадим структуру для круга и реализуем метод Area():

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

Где:

  • Circle имеет поле Radius (радиус)
  • Метод Area() вычисляет площадь по формуле πr²
  • Реализация привязана к типу Circle через receiver (c Circle)

Реализация для квадрата

Аналогично создадим структуру для квадрата:

type Square struct {
    Side float64
}

func (s Square) Area() float64 {
    return s.Side * s.Side
}

Где:

  • Square имеет поле Side (длина стороны)
  • Метод Area() вычисляет площадь как side²
  • Реализация также через receiver, но для типа Square

Пример использования

Покажем, как можно работать с этими реализациями через интерфейс:

func printArea(s Shape) {
    fmt.Printf("Area: %.2f\n", s.Area())
}

func main() {
    circle := Circle{Radius: 5}
    square := Square{Side: 4}

    printArea(circle) // Area: 78.54
    printArea(square) // Area: 16.00

    // Можно также хранить в переменной интерфейсного типа
    var shape Shape = Circle{Radius: 3}
    fmt.Println(shape.Area()) // 28.274333882308138
}

Преимущества такого подхода

  1. Полиморфизм: Функция printArea может работать с любым типом, реализующим Shape
  2. Расширяемость: Можно легко добавить новые фигуры (треугольник, прямоугольник)
  3. Инкапсуляция: Детали реализации скрыты за интерфейсом
  4. Тестируемость: Легко подменять реализации для тестов

Проверка реализации

Можно явно проверить, что тип реализует интерфейс:

var _ Shape = (*Circle)(nil) // Проверка на этапе компиляции

Дополнительные возможности

Интерфейс можно расширить, добавив например метод для периметра:

type Shape interface {
    Area() float64
    Perimeter() float64
}

Но тогда потребуется реализовать оба метода во всех структурах.

Резюмируем

  • Создали интерфейс Shape с методом Area()
  • Реализовали его для структур Circle и Square
  • Показали полиморфное использование через интерфейс
  • Интерфейсный подход делает код гибким и расширяемым
  • В Go реализация интерфейсов неявная - достаточно просто иметь нужные методы