Menu
Coddy logo textTech

Mehrere Structs einbetten

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

Go ermöglicht es dir, mehrere Strukturen in eine einzelne Struktur einzubetten und Verhaltensweisen aus verschiedenen Quellen zu kombinieren. Dies ähnelt der Mehrfachvererbung in anderen Sprachen, verwendet jedoch Gos Kompositionsansatz.

type Logger struct{}

func (l Logger) Log(msg string) string {
    return "LOG: " + msg
}

type Notifier struct{}

func (n Notifier) Notify(msg string) string {
    return "NOTIFY: " + msg
}

type Service struct {
    Name string
    Logger
    Notifier
}

Die Struktur Service hat nun Zugriff auf Methoden beider eingebetteten Typen:

func main() {
    s := Service{Name: "OrderService"}
    fmt.Println(s.Log("started"))      // LOG: gestartet
    fmt.Println(s.Notify("new order")) // NOTIFY: neue Bestellung
}

Beim Einbetten mehrerer Structs kann ein Namenskonflikt auftreten, wenn zwei eingebettete Typen Methoden mit demselben Namen haben. Go löst diese Mehrdeutigkeit nicht automatisch auf:

type A struct{}
func (A) Greet() string { return "Hello from A" }

type B struct{}
func (B) Greet() string { return "Hello from B" }

type Combined struct {
    A
    B
}

func main() {
    c := Combined{}
    // c.Greet() - Kompilierfehler: mehrdeutiger Selektor
    fmt.Println(c.A.Greet())  // Hello from A
    fmt.Println(c.B.Greet())  // Hello from B
}

Wenn Konflikte auftreten, musst du ausdrücklich angeben, die Methode welchen eingebetteten Typs du aufrufen möchtest, indem du den Typnamen als Qualifizierer verwendest.

challenge icon

Aufgabe

Einfach

Wir erstellen ein Smart-Home-Gerätesystem, das durch das Einbetten von Structs mehrere Funktionen kombiniert. Du erstellst ein Gerät, das sowohl die Beleuchtung steuern als auch Musik abspielen kann, indem du separate Controller-Typen einbettest.

Du organisierst deinen Code über drei Dateien:

  • controllers.go: Erstelle zwei unabhängige Controller-Structs, die unterschiedliche Funktionen bereitstellen:
    • Einen LightController mit einem Brightness-Feld (int) und einer SetLight(level int) string-Methode, die Light set to [level]% zurückgibt
    • Einen AudioController mit einem Volume-Feld (int) und einer SetVolume(level int) string-Methode, die Volume set to [level]% zurückgibt
    Beide Controller sollten außerdem eine Status() string-Methode besitzen. Dadurch entsteht ein Namenskonflikt, den du behandeln musst. LightController.Status() sollte Brightness: [Brightness]% zurückgeben und AudioController.Status() sollte Volume: [Volume]% zurückgeben.
  • device.go: Erstelle ein SmartDevice-Struct mit einem Name-Feld, das sowohl LightController als auch AudioController einbettet. Füge eine Methode namens FullStatus() string hinzu, die den Gerätenamen zusammen mit den Statusinformationen beider Controller zurückgibt, wobei du die Mehrdeutigkeit auflöst, indem du explizit die Status()-Methode jedes eingebetteten Typs aufrufst.
  • main.go: Lies die Gerätekonfiguration aus der Eingabe, erstelle ein SmartDevice, verwende die beförderten Methoden, um die Beleuchtungs- und Lautstärkepegel festzulegen, und zeige anschließend den vollständigen Status an.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Gerätename
  • Zeile 2: Anfänglicher Beleuchtungspegel (Ganzzahl)
  • Zeile 3: Anfänglicher Lautstärkepegel (Ganzzahl)
  • Zeile 4: Neuer festzulegender Beleuchtungspegel (Ganzzahl)
  • Zeile 5: Neuer festzulegender Lautstärkepegel (Ganzzahl)

Deine FullStatus()-Methode sollte Folgendes zurückgeben:

[Name] - [LightController.Status()], [AudioController.Status()]

Gib die Ergebnisse der Aufrufe von SetLight und SetVolume aus (die von den eingebetteten Typen befördert werden), und gib anschließend den vollständigen Status aus.

Wenn beispielsweise Living Room Hub, 50, 30, 75 und 60 angegeben werden, sollte deine Ausgabe wie folgt aussehen:

Light set to 75%
Volume set to 60%
Living Room Hub - Brightness: 75%, Volume: 60%

Beachte, dass SetLight und SetVolume durch Methodenbeförderung direkt auf SmartDevice zugänglich sind, während für Status() eine explizite Qualifizierung erforderlich ist, da beide eingebetteten Typen über diese Methode verfügen.

Probier es selbst

package main

import (
	"fmt"
)

func main() {
	// Eingabe lesen
	var name string
	fmt.Scanln(&name)

	var initialBrightness int
	fmt.Scanln(&initialBrightness)

	var initialVolume int
	fmt.Scanln(&initialVolume)

	var newBrightness int
	fmt.Scanln(&newBrightness)

	var newVolume int
	fmt.Scanln(&newVolume)

	// TODO: Erstelle ein SmartDevice mit dem gegebenen Namen und den Anfangswerten

	// TODO: Verwende die promovierte SetLight-Methode und gib das Ergebnis aus

	// TODO: Verwende die promovierte SetVolume-Methode und gib das Ergebnis aus

	// TODO: Gib den vollständigen Status mit der FullStatus()-Methode aus
}
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

Übe selbstständig: Online-Go-Compiler