Интерфейс с методами
Интерфейс с методами в Go определяет контракт, который должен реализовать тип. В интерфейсе перечисляются сигнатуры методов без их реализации. Тип удовлетворяет интерфейсу, если он реализует все методы с такими же именами, параметрами и возвращаемыми значениями. Это основа полиморфизма в Go.
Синтаксис
type InterfaceName interface {
MethodName(param1 Type1, param2 Type2) ReturnType
AnotherMethod(param Type) (ReturnType1, ReturnType2)
}
Для объявления интерфейса используется ключевое слово interface,
в фигурных скобках перечисляются методы. Каждый метод описывается
своим именем, параметрами и возвращаемыми значениями.
Пример
Давайте объявим интерфейс Shape с методами Area и Perimeter,
а затем реализуем его для структуры Rectangle:
package main
import "fmt"
type Shape interface {
Area() float64
Perimeter() float64
}
type Rectangle struct {
width float64
height float64
}
func (r Rectangle) Area() float64 {
return r.width * r.height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.width + r.height)
}
func main() {
rect := Rectangle{width: 5, height: 3}
var s Shape = rect
fmt.Println("Area:", s.Area())
fmt.Println("Perimeter:", s.Perimeter())
}
Результат выполнения кода:
"Area: 15"
"Perimeter: 16"
Структура Rectangle автоматически удовлетворяет интерфейсу Shape,
так как реализует оба метода. Переменная типа интерфейса может хранить
значение любого типа, реализующего этот интерфейс.
Пример
Создадим интерфейс Stringer с методом String и реализуем его
для структуры Person:
package main
import "fmt"
type Stringer interface {
String() string
}
type Person struct {
name string
age int
}
func (p Person) String() string {
return fmt.Sprintf("Name: %s, Age: %d", p.name, p.age)
}
func main() {
p := Person{name: "Alice", age: 30}
var s Stringer = p
fmt.Println(s.String())
}
Результат выполнения кода:
"Name: Alice, Age: 30"
Метод String возвращает строковое представление объекта.
Этот интерфейс широко используется в стандартной библиотеке,
например, в пакете fmt для форматированного вывода.
Пример
Интерфейсы могут содержать несколько методов с разными параметрами.
Рассмотрим интерфейс Calculator для математических операций:
package main
import "fmt"
type Calculator interface {
Add(a, b int) int
Subtract(a, b int) int
Multiply(a, b int) int
}
type BasicCalc struct{}
func (c BasicCalc) Add(a, b int) int {
return a + b
}
func (c BasicCalc) Subtract(a, b int) int {
return a - b
}
func (c BasicCalc) Multiply(a, b int) int {
return a * b
}
func main() {
calc := BasicCalc{}
var c Calculator = calc
fmt.Println("Add:", c.Add(10, 5))
fmt.Println("Subtract:", c.Subtract(10, 5))
fmt.Println("Multiply:", c.Multiply(10, 5))
}
Результат выполнения кода:
"Add: 15"
"Subtract: 5"
"Multiply: 50"
Тип BasicCalc реализует все три метода интерфейса Calculator
и может использоваться везде, где требуется этот интерфейс.
Смотрите также
-
объявление интерфейса
interface,
которое содержит общую информацию об интерфейсах -
неявную реализацию интерфейсов
implicit-implementation,
которая позволяет типам автоматически удовлетворять интерфейсам -
встраивание интерфейсов
embedding,
которое позволяет комбинировать интерфейсы -
интерфейс
error,
который является стандартным интерфейсом для обработки ошибок