Реализация интерфейса
Реализация интерфейса в Go - это процесс, при котором конкретный тип (структура или пользовательский тип) удовлетворяет требованиям интерфейса. Для реализации интерфейса тип должен определить все методы, объявленные в интерфейсе. В Go реализация интерфейса происходит неявно - нет необходимости явно указывать, что тип реализует интерфейс. Это делает код более гибким и упрощает тестирование.
Синтаксис реализации интерфейса
type InterfaceName interface {
MethodName(param type) returnType
}
type MyType struct {
// поля структуры
}
func (m MyType) MethodName(param type) returnType {
// реализация метода
return result
}
Пример базовой реализации интерфейса
Давайте создадим интерфейс 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("%s (%d years old)", p.Name, p.Age)
}
func main() {
person := Person{Name: "Alice", Age: 30}
var s Stringer = person
res := s.String()
fmt.Println(res)
}
Результат выполнения кода:
"Alice (30 years old)"
Пример реализации с указателем на структуру
Методы могут быть реализованы как с получателем-значением, так и с получателем-указателем. Рассмотрим пример с получателем-указателем, который позволяет изменять состояние структуры:
package main
import "fmt"
type Counter interface {
Increment()
Value() int
}
type MyCounter struct {
count int
}
func (c *MyCounter) Increment() {
c.count++
}
func (c *MyCounter) Value() int {
return c.count
}
func main() {
counter := &MyCounter{count: 0}
var c Counter = counter
c.Increment()
c.Increment()
res := c.Value()
fmt.Println(res)
}
Результат выполнения кода:
2
Пример реализации нескольких интерфейсов
Один тип может реализовывать несколько интерфейсов. Рассмотрим структуру, которая реализует два интерфейса - Reader и Writer:
package main
import "fmt"
type Reader interface {
Read() string
}
type Writer interface {
Write(data string)
}
type DataStore struct {
data string
}
func (d *DataStore) Read() string {
return d.data
}
func (d *DataStore) Write(data string) {
d.data = data
}
func main() {
store := &DataStore{data: "initial"}
var r Reader = store
var w Writer = store
w.Write("new data")
res := r.Read()
fmt.Println(res)
}
Результат выполнения кода:
"new data"
Пример неявной реализации интерфейса
В Go реализация интерфейса не требует явного объявления. Если тип имеет все методы интерфейса, он автоматически считается реализующим этот интерфейс. Это позволяет легко добавлять новые реализации без изменения существующего кода:
package main
import "fmt"
type Shape interface {
Area() float64
}
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
func printArea(s Shape) {
res := s.Area()
fmt.Println(res)
}
func main() {
rect := Rectangle{Width: 5, Height: 10}
circle := Circle{Radius: 3}
printArea(rect)
printArea(circle)
}
Результат выполнения кода:
50
28.26
Смотрите также
-
интерфейсы в целом
interface,
общее понятие и назначение интерфейсов в Go -
неявную реализацию интерфейсов
implicit-implementation,
которая позволяет реализовывать интерфейсы без явного объявления -
методы интерфейсов
methods,
которые должны быть реализованы для удовлетворения интерфейса -
интерфейс
error,
встроенный интерфейс для обработки ошибок в Go