Menu
Coddy logo textTech

Shadowing eingebetteter Methoden

Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 39 von 107.

Manchmal müssen Sie für das äußere Struct eine eigene Implementierung einer Methode bereitstellen, die der eingebettete Typ bereits besitzt. Dies wird als Shadowing bezeichnet und ermöglicht es Ihnen, weitergereichte Methoden durch benutzerdefiniertes Verhalten zu überschreiben.

Wenn Sie eine Methode für das äußere Struct mit demselben Namen wie eine eingebettete Methode definieren, hat die äußere Methode Vorrang:

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!"
}

Wenn Sie nun Speak() für einen Dog aufrufen, wird die äußere Methode verwendet:

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

Die eingebettete Methode ist nicht verschwunden. Sie können weiterhin explizit über den Namen des eingebetteten Typs darauf zugreifen. Dieses Muster ist nützlich, wenn Sie das Verhalten anpassen möchten, während die ursprüngliche Implementierung verfügbar bleibt, um sie vielleicht aus Ihrer überschreibenden Methode heraus aufzurufen:

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

Shadowing gibt Ihnen die Kontrolle darüber, welches Verhalten offengelegt wird, während der Zugriff auf das Original durch explizite Qualifizierung erhalten bleibt.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Benachrichtigungssystem bauen, bei dem verschiedene Benachrichtigungskanäle anpassen können, wie sie Nachrichten formatieren und zustellen. Sie werden Method Shadowing verwenden, um spezifischen Kanälen zu ermöglichen, das Standardverhalten zu überschreiben, während sie bei Bedarf weiterhin auf die ursprüngliche Implementierung zugreifen können.

Sie werden Ihren Code über drei Dateien organisieren:

  • base.go: Erstellen Sie ein BaseNotification-Struct mit den Feldern Title und Priority (beides Strings). Geben Sie ihm eine Format() string-Methode, die die Benachrichtigung in einem Standardformat zurückgibt: [Priority] Title.
  • channels.go: Erstellen Sie zwei Benachrichtigungskanaltypen, die BaseNotification einbetten und die Format-Methode mit ihren eigenen Implementierungen überschatten (shadowing):
    • EmailNotification mit einem Recipient-Feld — sein Format() sollte Email to [Recipient]: [Priority] Title zurückgeben
    • SlackNotification mit einem Channel-Feld — sein Format() sollte die eingebettete BaseNotification.Format()-Methode aufrufen und dem Ergebnis #[Channel]: voranstellen
  • main.go: Lesen Sie die Benachrichtigungsdetails aus der Eingabe, erstellen Sie beide Arten von Benachrichtigungen und demonstrieren Sie das Shadowing durch das Drucken von:
    1. Der formatierten Ausgabe der EmailNotification (unter Verwendung ihrer überschatteten Methode)
    2. Dem Basisformat der EmailNotification (durch explizites Aufrufen der eingebetteten Methode)
    3. Der formatierten Ausgabe der SlackNotification (die intern die Basismethode verwendet)

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Benachrichtigungstitel
  • Zeile 2: Prioritätsstufe
  • Zeile 3: E-Mail-Empfänger
  • Zeile 4: Slack-Kanalname

Zum Beispiel, gegeben Server Alert, HIGH, admin@company.com und ops-alerts, sollte Ihre Ausgabe wie folgt aussehen:

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

Beachten Sie, wie EmailNotification die Basisformatierung vollständig ersetzt, während SlackNotification sie erweitert, indem sie die ursprüngliche Methode aufruft und den Kanalkontext hinzufügt. Beide Ansätze demonstrieren verschiedene Wege, Method Shadowing effektiv einzusetzen.

Spickzettel

Wenn Sie eine Methode für ein äußeres Struct mit demselben Namen wie eine Methode eines eingebetteten Typs definieren, überdeckt (shadows) die äußere Methode die eingebettete Methode:

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!"
}

Beim Aufruf der Methode auf dem äußeren Struct hat die äußere Methode Vorrang:

d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}

fmt.Println(d.Speak())        // Woof! - Methode von Dog
fmt.Println(d.Animal.Speak()) // Some sound - Methode von Animal

Die eingebettete Methode bleibt durch explizite Qualifizierung unter Verwendung des Namens des eingebetteten Typs zugänglich. Sie können die ursprüngliche Implementierung aus der überschreibenden Methode heraus aufrufen:

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

Probier es selbst

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Benachrichtigungstitel lesen
	scanner.Scan()
	title := scanner.Text()
	
	// Prioritätsstufe lesen
	scanner.Scan()
	priority := scanner.Text()
	
	// E-Mail-Empfänger lesen
	scanner.Scan()
	recipient := scanner.Text()
	
	// Slack-Kanalnamen lesen
	scanner.Scan()
	channel := scanner.Text()
	
	// TODO: Erstelle eine EmailNotification mit der Basis-Benachrichtigung, title, priority und recipient
	
	// TODO: Erstelle eine SlackNotification mit der Basis-Benachrichtigung, title, priority und channel
	
	// TODO: Gib die formatierte Ausgabe der EmailNotification aus (unter Verwendung ihrer überschatteten Methode)
	
	// TODO: Gib das Basisformat der EmailNotification aus (durch explizites Aufrufen der eingebetteten Methode)
	
	// TODO: Gib die formatierte Ausgabe der SlackNotification aus
	
	fmt.Println() // Platzhalter - beim Implementieren entfernen
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung