Promowanie metod
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 36 z 107.
Tak jak osadzanie struktur przenosi pola do zewnętrznej struktury, Go przenosi również metody z osadzonych typów. Oznacza to, że możesz wywoływać metody zdefiniowane w osadzonej strukturze bezpośrednio na zewnętrznej strukturze.
type Engine struct {
Horsepower int
}
func (e Engine) Start() string {
return "Engine started"
}
type Car struct {
Model string
Engine // osadzony
}
Ponieważ Car osadza Engine, metoda Start() jest automatycznie promowana:
func main() {
c := Car{
Model: "Sedan",
Engine: Engine{Horsepower: 200},
}
fmt.Println(c.Start()) // Silnik został uruchomiony
fmt.Println(c.Engine.Start()) // również działa
}
Ta promocja ma ważną konsekwencję dla interfejsów. Jeśli typ osadzony spełnia wymagania interfejsu, typ zewnętrzny również automatycznie je spełnia:
type Starter interface {
Start() string
}
func Ignite(s Starter) {
fmt.Println(s.Start())
}
func main() {
c := Car{Model: "Sedan", Engine: Engine{Horsepower: 200}}
Ignite(c) // Car spełnia interfejs Starter dzięki Engine
}
Typ Car nigdy jawnie nie implementuje Starter, a mimo to spełnia wymagania interfejsu, ponieważ osadzony w nim typ Engine ma wymaganą metodę. W ten sposób Go umożliwia ponowne wykorzystanie zachowania bez tradycyjnego dziedziczenia.
Wyzwanie
ŁatwyZbudujmy system odtwarzacza muzyki, który pokazuje, jak metody osadzonych typów są promowane do typu zewnętrznego oraz jak dzięki temu kompozycja umożliwia spełnienie wymagań interfejsu.
Rozmieścisz kod w dwóch plikach:
audio.go: Utwórz podstawowe elementy odtwarzacza muzyki:- Strukturę
AudioPlayerz polemBrand(string) oraz metodąPlay() string, która zwraca[Brand] playing audio - Interfejs
Playable, który wymaga metodyPlay() string - Strukturę
Smartphonez polemModel, która osadzaAudioPlayer - Strukturę
Tabletz polemModel, która osadzaAudioPlayer
- Strukturę
main.go: Utwórz funkcję o nazwieStartPlayback, która przyjmuje dowolny typ spełniający interfejsPlayablei zwraca wynik wywołaniaPlay(). Odczytaj informacje o urządzeniach z wejścia, utwórz zarówno smartfon, jak i tablet, a następnie pokaż, że oba spełniają interfejsPlayabledzięki osadzonemuAudioPlayer, mimo że żaden z tych typów nie implementuje jawnie metodyPlay().
Podane zostaną następujące dane wejściowe:
- Wiersz 1: Nazwa modelu smartfona
- Wiersz 2: Marka odtwarzacza audio w smartfonie
- Wiersz 3: Nazwa modelu tabletu
- Wiersz 4: Marka odtwarzacza audio w tablecie
Dla każdego urządzenia wypisz jego model, a następnie wynik przekazania go do funkcji StartPlayback.
Na przykład dla danych iPhone 15, Apple Audio, iPad Pro i Beats wynik powinien wyglądać następująco:
iPhone 15
Apple Audio playing audio
iPad Pro
Beats playing audioZwróć uwagę, że zarówno Smartphone, jak i Tablet można przekazać do funkcji StartPlayback, ponieważ metoda Play() z AudioPlayer jest automatycznie promowana do każdego typu zewnętrznego, dzięki czemu spełnia on wymagania interfejsu Playable bez dodatkowego kodu.
Spróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
)
// TODO: Utwórz funkcję StartPlayback, która przyjmuje dowolny obiekt Playable
// i zwraca wynik wywołania Play()
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Odczytaj model smartfona
scanner.Scan()
smartphoneModel := scanner.Text()
// Odczytaj markę systemu audio smartfona
scanner.Scan()
smartphoneBrand := scanner.Text()
// Odczytaj model tabletu
scanner.Scan()
tabletModel := scanner.Text()
// Odczytaj markę systemu audio tabletu
scanner.Scan()
tabletBrand := scanner.Text()
// TODO: Utwórz obiekt Smartphone z osadzonym AudioPlayer
// TODO: Utwórz obiekt Tablet z osadzonym AudioPlayer
// TODO: Wypisz model smartfona, a następnie wywołaj StartPlayback, przekazując smartfon
// TODO: Wypisz model tabletu, a następnie wywołaj StartPlayback, przekazując tablet
_ = smartphoneModel
_ = smartphoneBrand
_ = tabletModel
_ = tabletBrand
fmt.Println("TODO: Complete the implementation")
}
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