Menu
Coddy logo textTech

Przesłanianie osadzonych metod

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 39 z 107.

Czasami zewnętrzna struktura musi dostarczyć własną implementację metody, którą ma już osadzony typ. Nazywa się to przesłanianiem i pozwala zastępować promowane metody własnym zachowaniem.

Gdy zdefiniujesz metodę w strukturze zewnętrznej o tej samej nazwie co metoda osadzona, pierwszeństwo ma metoda zewnętrzna:

type Animal struct {
    Name string
}

func (a Animal) Speak() string {
    return "Some sound"
}

type Dog struct {
    Animal
    Breed string
}

func (d Dog) Speak() string {
    return "Woof!"
}

Teraz, gdy wywołujesz Speak() na obiekcie Dog, używana jest metoda zewnętrzna:

func main() {
    d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}
    
    fmt.Println(d.Speak())        // Woof! - metoda Dog
    fmt.Println(d.Animal.Speak()) // Some sound - metoda Animal
}

Osadzona metoda nie zniknęła. Nadal możesz uzyskać do niej dostęp jawnie za pośrednictwem nazwy osadzonego typu. Ten wzorzec jest przydatny, gdy chcesz dostosować zachowanie, zachowując dostęp do oryginalnej implementacji, na przykład aby wywołać ją z poziomu nadpisywanej metody:

func (d Dog) Speak() string {
    return d.Animal.Speak() + " (but actually Woof!)"
}

Przesłanianie daje Ci kontrolę nad tym, które zachowanie jest udostępniane, a jednocześnie pozwala uzyskać dostęp do oryginalnego za pomocą jawnej kwalifikacji.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system powiadomień, w którym różne kanały powiadomień mogą dostosowywać formatowanie i dostarczanie wiadomości. Użyjesz przesłaniania metod, aby poszczególne kanały mogły zastępować domyślne zachowanie, a jednocześnie w razie potrzeby uzyskiwać dostęp do oryginalnej implementacji.

Rozmieścisz kod w trzech plikach:

  • base.go: Utwórz strukturę BaseNotification z polami Title i Priority (oba typu string). Dodaj do niej metodę Format() string, która zwraca powiadomienie w standardowym formacie: [Priority] Title.
  • channels.go: Utwórz dwa typy kanałów powiadomień, które osadzają BaseNotification i przesłaniają metodę Format, stosując własne implementacje:
    • EmailNotification z polem Recipient. Metoda Format() powinna zwracać Email to [Recipient]: [Priority] Title
    • SlackNotification z polem Channel. Metoda Format() powinna wywoływać osadzoną metodę BaseNotification.Format() i dodawać na początku wyniku #[Channel]:
  • main.go: Odczytaj szczegóły powiadomienia z wejścia, utwórz oba typy powiadomień i zademonstruj przesłanianie, wypisując:
    1. Sformatowany wynik EmailNotification (przy użyciu jego przesłoniętej metody)
    2. Podstawowy format EmailNotification (przez jawne wywołanie osadzonej metody)
    3. Sformatowany wynik SlackNotification (który wewnętrznie korzysta z podstawowej metody)

Zostaną podane następujące dane wejściowe:

  • Wiersz 1: Tytuł powiadomienia
  • Wiersz 2: Poziom priorytetu
  • Wiersz 3: Odbiorca wiadomości e-mail
  • Wiersz 4: Nazwa kanału Slack

Na przykład dla danych Server Alert, HIGH, admin@company.com i ops-alerts wynik powinien wyglądać następująco:

Email to admin@company.com: HIGH Server Alert
[HIGH] Server Alert
#ops-alerts: [HIGH] Server Alert

Zwróć uwagę, że EmailNotification całkowicie zastępuje podstawowe formatowanie, podczas gdy SlackNotification rozszerza je, wywołując oryginalną metodę i dodając kontekst kanału. Oba podejścia pokazują różne sposoby efektywnego wykorzystania przesłaniania metod.

Spróbuj swoich sił

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Odczytaj tytuł powiadomienia
	scanner.Scan()
	title := scanner.Text()
	
	// Odczytaj poziom priorytetu
	scanner.Scan()
	priority := scanner.Text()
	
	// Odczytaj odbiorcę wiadomości e-mail
	scanner.Scan()
	recipient := scanner.Text()
	
	// Odczytaj nazwę kanału Slack
	scanner.Scan()
	channel := scanner.Text()
	
	// TODO: Utwórz EmailNotification z bazowym powiadomieniem, tytułem, priorytetem i odbiorcą
	
	// TODO: Utwórz SlackNotification z bazowym powiadomieniem, tytułem, priorytetem i kanałem
	
	// TODO: Wypisz sformatowany wynik EmailNotification (używając jego metody przesłaniającej metodę osadzonego typu)
	
	// TODO: Wypisz bazowy format EmailNotification (jawnie wywołując metodę osadzonego typu)
	
	// TODO: Wypisz sformatowany wynik SlackNotification
	
	fmt.Println() // Element zastępczy – usuń podczas implementacji
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online