Przejdź do głównej treści
eLearner.app
Moduł 6 · Lekcja 1 z 526/50 w kursie~12 min
Lekcje modułu (1/5)

Interfejsy: definiowanie zachowania

Interfejs w Go to zestaw sygnatur metod. Wartość implementuje interfejs, jeśli ma wszystkie te metody — nie implements, brak extends, brak wyraźnej rejestracji. To jest model często nazywany „pisaniem strukturalnym” lub „statycznym pisaniem kaczym”: kompilator sprawdza zgodność w czasie kompilacji, ale na podstawie kształtu, a nie na deklaracjach.

Deklarowanie interfejsu

Go
type Greeter interface {
    Greet() string
}

Konwencja: nazwy kończące się na -er dla interfejsów jednometodowych (KODEF1, KODEF2, KODEF3, KODEF4). Małe interfejsy (1–2 metody) są idiomatyczne: standardowa biblioteka jest pełna maleńkie interfejsy, które się ze sobą łączą (io.ReadWriter, KODEF6, …).

Niejawna implementacja

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())

Brak słowa kluczowego. Jeśli typ posiada metody, można go do niego przypisać zmienna tego typu interfejsu. To wszystko.

Polimorfizm poprzez interfejs

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 akceptuje dowolny typ, który spełnia wymagania Greeter. To jest droga Go robienia polimorfizmu: żadnych hierarchii, tylko możliwości.

Pusty interfejs

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

interface{} (lub any od wersji 1.18) nie wymaga żadnych metod, więc dowolnych wartość go zaspokaja. Przydatne w przypadku kontenerów ogólnych, ale do wyodrębnienia konkretna wartość, której potrzebujesz twierdzenie typu lub przełącznik typu (kolejne lekcje).

Zestaw metod: wartość vs odbiornik wskaźnika (podgląd)

Przypomnij sobie z Modułu 5:

  • Metody z odbiornikiem wartości znajdują się w zestawie metod zarówno T, jak i *T.
  • Metody z odbiornikiem wskaźników znajdują się TYLKO w zestawie metod *T.

Praktyczna konsekwencja:

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

Gdy metoda ma odbiornik wskaźników, należy przypisać do niego wskaźnik zmienna interfejsu.

Spróbuj

Ćwiczenie#go.m6.l1.e1
Próby: 0Ładowanie...

Zdefiniuj interfejs Greeter za pomocą pojedynczego ciągu znaków metody Greet().

Ładowanie edytora...
Pokaż wskazówkę

Składnia: `type Name interface { Method(args) return }`.

Rozwiązanie dostępne po 3 próbach

Ćwiczenie#go.m6.l1.e2
Próby: 0Ładowanie...

Zaimplementuj Greeter na robocie nowego typu z ciągiem identyfikacyjnym pola; metoda zwraca „bip” + ​​ID.

Ładowanie edytora...
Pokaż wskazówkę

Brak `implements`: po prostu zdefiniuj metodę z właściwym podpisem.

Rozwiązanie dostępne po 3 próbach

Quiz#go.m6.l1.e3
Gotowe

Jak zadeklarować, że typ P implementuje interfejs Greeter?

Go
type P struct{}
// ?
Opcje odpowiedzi

Podsumowanie

  • Interfejs = zestaw sygnatur metod; brak KODU0.
  • Niejawna implementacja: wystarczy mieć metody z właściwym podpisem.
  • Idiomatyczny: małe interfejsy (1–2 metody), nazwy w -er.
  • interface{} / any: przyjmuje dowolną wartość, traci bezpieczeństwo typu.
  • Zestaw metod: odbiornik wskaźnika → tylko *T spełnia wymagania interfejsu.
  • Idź na polimorfizm: parametry typu interfejsu, bez hierarchii.