Wprowadzenie do interfejsów
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 25 z 107.
Interfejs w Go definiuje zestaw sygnatur metod bez ich implementowania. Opisuje, co dany typ potrafi robić, a nie jak to robi. Każdy typ, który implementuje wszystkie metody interfejsu, automatycznie spełnia wymagania tego interfejsu.
Oto jak definiujesz interfejs:
type Speaker interface {
Speak() string
}Ten interfejs Speaker wymaga, aby każdy typ, który go implementuje, miał metodę Speak(), która zwraca ciąg znaków. Teraz każda struktura z tą metodą może być używana wszędzie tam, gdzie oczekiwany jest typ Speaker.
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return d.Name + " says woof!"
}
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return c.Name + " says meow!"
}Zarówno Dog, jak i Cat spełniają interfejs Speaker, ponieważ każda z nich ma metodę Speak() o poprawnej sygnaturze. Możesz teraz pisać funkcje, które przyjmują dowolny Speaker:
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
dog := Dog{Name: "Buddy"}
cat := Cat{Name: "Whiskers"}
MakeSound(dog) // Buddy mówi hau!
MakeSound(cat) // Whiskers mówi miau!
}Interfejsy umożliwiają pisanie elastycznego, wielokrotnego użytku kodu, który działa z dowolnym typem spełniającym wymagania interfejsu, niezależnie od jego implementacji.
Wyzwanie
ŁatwyZbudujmy system opisu pojazdów, który pokazuje, jak interfejsy pozwalają różnym typom współdzielić wspólne zachowanie. Utworzysz interfejs, który mogą spełniać różne typy pojazdów, a następnie wykorzystasz go do jednolitego opisywania dowolnego pojazdu.
Rozmieścisz kod w dwóch plikach:
vehicles.go: Zdefiniuj interfejsDescriberz jedną metodąDescribe() string. Następnie utwórz dwie struktury spełniające ten interfejs:Carz polamiBrandiModel(oba typu string)Bicyclez polamiType(typu string) iGears(typu int)
Describe(), która zwraca opisowy ciąg znaków dotyczący pojazdu.main.go: Utwórz funkcję o nazwiePrintDescription, która przyjmuje dowolny obiekt implementującyDescriberi wyświetla wynik wywołania jego metodyDescribe(). Odczytaj informacje o pojazdach z wejścia, utwórz zarówno samochód, jak i rower, a następnie użyj swojej funkcji, aby wyświetlić opis każdego z nich.
Zostaną podane następujące dane wejściowe:
- Wiersz 1: Marka samochodu
- Wiersz 2: Model samochodu
- Wiersz 3: Typ roweru
- Wiersz 4: Liczba biegów (liczba całkowita)
Twoje metody Describe() powinny zwracać ciągi znaków w następujących formatach:
- Samochód:
[Brand] [Model] - Rower:
[Type] bike with [Gears] gears
Na przykład dla danych Toyota, Camry, Mountain i 21 wynik powinien wyglądać tak:
Toyota Camry
Mountain bike with 21 gearsKluczowa myśl jest taka, że Twoja funkcja PrintDescription działa z dowolnym typem, który ma metodę Describe(). Nie musi wiedzieć, czy ma do czynienia z samochodem, rowerem czy innym typem pojazdu, który możesz dodać później.
Spróbuj swoich sił
package main
import (
"fmt"
)
// TODO: Utwórz funkcję PrintDescription, która przyjmuje dowolny obiekt typu Describer
// i wypisuje wynik wywołania jego metody Describe()
func main() {
// Wczytaj dane wejściowe
var carBrand string
var carModel string
var bicycleType string
var gears int
fmt.Scanln(&carBrand)
fmt.Scanln(&carModel)
fmt.Scanln(&bicycleType)
fmt.Scanln(&gears)
// TODO: Utwórz obiekt Car z marką i modelem z danych wejściowych
// TODO: Utwórz obiekt Bicycle z typem i liczbą biegów z danych wejściowych
// TODO: Użyj PrintDescription, aby wypisać opis samochodu
// TODO: Użyj PrintDescription, aby wypisać opis roweru
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP w Go
Pliki zewnętrzneObszar roboczy i moduły GoPakiety i importyNazwy eksportowane i nieeksportowaneWprowadzenie do OOP w GoStruktury jako klasyDefiniowanie metod dla strukturOdbiorniki wskaźnikowe i wartościoweInicjalizacja strukturFunkcje konstruktoraPodsumowanie – prosty kalkulator4Interfejsy
Wprowadzenie do interfejsówImplementacja niejawnaInterfejs jako kontraktPusty interfejs (any)Asercja typuPrzełącznik typówKompozycja interfejsówInterfejsy Stringer i ErrorPowtórka — kalkulator figur7Hermetyzacja
Pola eksportowane i nieeksportowaneHermetyzacja na poziomie pakietuMetody pobierające i ustawiająceUkrywanie informacji w GoPowtórka – dane studentów10Typy generyczne (Go 1.18+)
Wprowadzenie do typów generycznychParametry typówOgraniczenia typówStruktury generyczneObejście ograniczeń metod generycznychPodsumowanie — generyczna kolekcja2Typy i struktury w praktyce
Typy proste i złożoneDefiniowanie własnych typówTagi pól strukturStruktury anonimoweStruktury zagnieżdżoneWartości zerowe i domyślnePodsumowanie – książka kontaktów5Kompozycja zamiast dziedziczenia
Dlaczego Go nie ma dziedziczeniaPodstawy osadzania strukturPromowanie metodOsadzanie wielu strukturOsadzanie a agregacjaPrzesłanianie osadzonych metodPodsumowanie — hierarchia pracowników8Obsługa błędów i programowanie obiektowe
Interfejs błęduWłasne typy błędówOpakowywanie błędów (fmt.Errorf)Błędy wartowniczeerrors.Is() i errors.As()Panic, Defer i RecoverPodsumowanie — parser plików3Wskaźniki i pamięć
Podstawy wskaźników w GoWskaźniki do strukturPrzekazywanie przez wartość a przez referencjęFunkcja new()Odśmiecanie pamięci w GoPowtórka — kreator listy wiązanej6Polimorfizm w Go
Polimorfizm za pomocą interfejsówDuck typing w GoZasady spełniania interfejsówKolekcje polimorficzneWstrzykiwanie zależnościPowtórka — procesor płatności9Współbieżność i OOP
Podstawy goroutinesKanały i komunikacjaKanały buforowane i niebuforowaneInstrukcja selectsync.Mutex i sync.RWMutexsync.WaitGroupProjektowanie struktur bezpiecznych wątkowoPowtórka – pula workerów12Zaawansowane zagadnienia programowania obiektowego
Wzorzec opcji funkcyjnychWzorzec Builder w GoŁańcuchowe wywoływanie metodAliasy typów a definicje typówPodstawy refleksjiPrzegląd generowania koduPoćwicz samodzielnie: Kompilator Go online