Перейти до основного вмісту
Модуль 6 · Урок 1 із 526/50 у курсі~12 min
Модульні уроки (1/5)

Інтерфейси: визначення поведінки

Інтерфейс у Go — це набір сигнатур методів. Значення реалізує інтерфейс, якщо він має всі ці методи — ні implements, ні extends, немає явної реєстрації. Це модель, яку часто називають "структурною типізацією" або "статичною типізацією": компілятор перевіряє відповідність під час компіляції, але на основі формі, а не на деклараціях.

Оголошення інтерфейсу

Go
type Greeter interface {
    Greet() string
}

Угода: імена, що закінчуються на -er для однометодних інтерфейсів (Reader, Writer, Stringer, Closer). Невеликі інтерфейси (1–2 методи) є ідіоматичними: стандартна бібліотека повна маленькі інтерфейси, які складаються разом (io.ReadWriter, io.ReadCloser, …).

Імпліцитна реалізація

Go
type Person struct{ Name string }

func (p Person) Greet() string {
    return "ciao " + p.Name
}

// Person satisfies Greeter because it has the required method.
var s Greeter = Person{Name: "Ada"}
fmt.Println(s.Greet())

Немає ключового слова. Якщо тип має методи, його можна призначити змінна цього типу інтерфейсу. Ось і все.

Поліморфізм через інтерфейс

Go
type Robot struct{ ID string }
func (r Robot) Greet() string { return "bip " + r.ID }

func greet(s Greeter) {
    fmt.Println(s.Greet())
}

greet(Person{Name: "Ada"})
greet(Robot{ID: "R2"})

greet приймає будь-який тип, який задовольняє Greeter. Це шлях Go створення поліморфізму: жодних ієрархій, лише можливості.

Порожній інтерфейс

Go
var x interface{} = 42
var y any = "ciao"   // any is the built-in alias of interface{}

interface{} (або any починаючи з Go 1.18) не вимагає методів, тому будь-які цінність його задовольняє. Корисно для загальних контейнерів, але для вилучення конкретне значення, яке вам потрібно твердження типу або перемикач типу (наступні уроки).

Набір методів: значення проти приймача покажчика (попередній перегляд)

Пригадайте з модуля 5:

  • Методи з приймачем значення є в наборі методів як T, так і *T.
  • Методи з приймачем вказівника є ТІЛЬКИ в наборі методів *T.

Практичний наслідок:

Go
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }

type Incrementer interface { Inc() }

var i Incrementer = &Counter{}   // OK: *Counter has Inc()
// var j Incrementer = Counter{} // ERROR: Counter (value) does NOT

Якщо метод має приймача вказівника, ви повинні призначити вказівник інтерфейсна змінна.

Спробуйте

вправи#go.m6.l1.e1
Спроби: 0Завантаження…

Визначте інтерфейс Greeter за допомогою одного рядка методу Greet().

Завантаження редактора…
Показати підказку

Синтаксис: `тип Назва інтерфейсу { Метод (аргументи) повернення }`.

Рішення доступне після 3 спроб

вправи#go.m6.l1.e2
Спроби: 0Завантаження…

Реалізуйте Greeter на новому типі Robot із рядком ID поля; метод повертає 'bip ' + ID.

Завантаження редактора…
Показати підказку

Ніяких `реалізацій`: просто визначте метод із правильною сигнатурою.

Рішення доступне після 3 спроб

Quiz#go.m6.l1.e3
Готовий

Як оголосити, що тип P реалізує інтерфейс Greeter?

Go
type P struct{}
// ?
Варіанти відповідей

Підведення підсумків

  • Інтерфейс = набір сигнатур методу; ні implements.
  • Неявна реалізація: просто мати методи з правильною сигнатурою.
  • Ідіоматичні: малі інтерфейси (1–2 методи), імена в -er.
  • interface{} / any: приймає будь-яке значення, втрачає безпеку типу.
  • Набір методів: приймач вказівника → тільки *T задовольняє інтерфейс. — Поліморфізм Go: параметри типу інтерфейсу, відсутність ієрархій.