Неявная реализация интерфейса
Неявная реализация интерфейса означает, что тип в Go автоматически
удовлетворяет интерфейсу, если он определяет все методы этого
интерфейса. Нам не нужно явно указывать, что тип реализует
интерфейс, как в других языках (например, с помощью ключевого
слова implements). Достаточно просто определить методы,
и компилятор Go сам определит, соответствует ли тип интерфейсу.
Это делает систему интерфейсов в Go гибкой и удобной для
разработки.
Синтаксис
type InterfaceName interface {
MethodName(param type) returnType
}
type MyType struct {
// поля
}
func (m MyType) MethodName(param type) returnType {
// реализация метода
}
Для неявной реализации интерфейса достаточно определить все методы, объявленные в интерфейсе, для нашего типа. После этого переменная нашего типа может быть присвоена переменной типа интерфейса без дополнительных действий.
Пример
Давайте определим простой интерфейс Shape с методом
Area, который возвращает площадь фигуры. Затем создадим
структуру Rectangle и реализуем для нее метод
Area. Благодаря неявной реализации, структура
Rectangle автоматически будет удовлетворять интерфейсу
Shape:
package main
import "fmt"
type Shape interface {
Area() float64
}
type Rectangle struct {
width, height float64
}
func (r Rectangle) Area() float64 {
return r.width * r.height
}
func main() {
rect := Rectangle{width: 10, height: 5}
var s Shape = rect
res := s.Area()
fmt.Println(res)
}
Результат выполнения кода:
50
Обратите внимание, что мы нигде не писали, что
Rectangle реализует Shape. Просто наличие метода
Area с правильной сигнатурой делает это автоматически.
Пример
Неявная реализация позволяет использовать интерфейсы как
контракты, которые могут быть удовлетворены любым типом,
определяющим нужные методы. Например, интерфейс Stringer
из пакета fmt требует метод String. Реализуем его
для структуры Person:
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s (%d years)", p.Name, p.Age)
}
func main() {
p := Person{Name: "Alice", Age: 30}
res := p.String()
fmt.Println(res)
}
Результат выполнения кода:
"Alice (30 years)"
Теперь тип Person автоматически реализует интерфейс
Stringer, и его можно использовать в функциях, ожидающих
этот интерфейс, например, в fmt.Println.
Смотрите также
-
статью
interface,
в которой описано объявление интерфейсов в Go -
статью
methods,
которая описывает методы и их связь с интерфейсами -
статью
empty-interface,
которая рассматривает пустой интерфейс и его применение -
статью
type-assertion,
которая описывает приведение типов интерфейсов