Menu
Coddy logo textTech

Polymorphismus über Interfaces

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

Polymorphismus ermöglicht es, verschiedene Typen über eine gemeinsame Schnittstelle einheitlich zu behandeln. In Go wird dies vollständig durch Interfaces erreicht, ohne Vererbung oder Klassenhierarchien.

Wenn eine Funktion einen Schnittstellentyp als Parameter akzeptiert, kann jeder konkrete Typ übergeben werden, der diese Schnittstelle implementiert. Die Funktion muss den spezifischen Typ nicht kennen. Sie berücksichtigt nur das von der Schnittstelle definierte Verhalten:

type Speaker interface {
    Speak() string
}

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

type Cat struct{ Name string }
func (c Cat) Speak() string { return "Meow!" }

func MakeSound(s Speaker) {
    fmt.Println(s.Speak())
}

Jetzt funktioniert MakeSound mit jedem Typ, der über eine Speak()-Methode verfügt:

func main() {
    dog := Dog{Name: "Rex"}
    cat := Cat{Name: "Whiskers"}
    
    MakeSound(dog)  // Wuff!
    MakeSound(cat)  // Miau!
}

Der gleiche Funktionsaufruf erzeugt je nach tatsächlich übergebenem Typ ein unterschiedliches Verhalten. Das ist Polymorphismus in Aktion. Die Funktion MakeSound wird einmal geschrieben, funktioniert aber mit einer unbegrenzten Anzahl von Typen, solange diese das Speaker-Interface erfüllen.

Dieser Ansatz hält deinen Code flexibel und erweiterbar. Das Hinzufügen eines neuen Typs, der spricht, erfordert keine Änderungen an vorhandenen Funktionen. Implementiere einfach die Schnittstelle, und es funktioniert automatisch.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Fahrzeugbeschreibungssystem, das Polymorphie in Aktion demonstriert. Du wirst verschiedene Fahrzeugtypen erstellen, die über ein Interface ein gemeinsames Verhalten teilen, und anschließend eine einzelne Funktion schreiben, die mit jedem Fahrzeug funktioniert.

Du wirst deinen Code auf zwei Dateien verteilen:

  • vehicles.go: Definiere ein Describer-Interface, das eine Describe() string-Methode erfordert. Erstelle anschließend drei Fahrzeugtypen, die dieses Interface jeweils auf ihre eigene Weise implementieren:
    • Car mit den Feldern Brand und Model. Die Methode Describe() gibt Car: [Brand] [Model] zurück
    • Motorcycle mit den Feldern Brand und EngineCC (int). Die Methode Describe() gibt Motorcycle: [Brand] [EngineCC]cc zurück
    • Bicycle mit dem Feld Type (zum Beispiel "Mountain" oder "Road"). Die Methode Describe() gibt Bicycle: [Type] zurück
  • main.go: Erstelle eine Funktion namens PrintDescription, die jedes Describer akzeptiert und das Ergebnis des Aufrufs von Describe() ausgibt. Lies die Fahrzeugdetails aus der Eingabe ein, erstelle jeweils ein Fahrzeug jedes Typs und übergib jedes davon an PrintDescription, um zu demonstrieren, dass dieselbe Funktion mit allen drei verschiedenen Typen funktioniert.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Automarke
  • Zeile 2: Automodell
  • Zeile 3: Motorradmarke
  • Zeile 4: Motorrad-Motorhubraum in CC (Ganzzahl)
  • Zeile 5: Fahrradtyp

Wenn beispielsweise Toyota, Camry, Honda, 600 und Mountain gegeben sind, sollte deine Ausgabe folgendermaßen aussehen:

Car: Toyota Camry
Motorcycle: Honda 600cc
Bicycle: Mountain

Beachte, dass PrintDescription nicht wissen muss, ob es ein Car, Motorcycle oder Bicycle erhält. Es ruft einfach Describe() auf, und jeder Typ antwortet mit seiner eigenen eindeutigen Ausgabe. Das ist Polymorphie: eine Funktion, mehrere Verhaltensweisen.

Probier es selbst

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// TODO: Erstelle eine Funktion namens PrintDescription, die einen beliebigen Describer akzeptiert
// und das Ergebnis des Aufrufs von Describe() ausgibt

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Autodetails lesen
	carBrand, _ := reader.ReadString('\n')
	carBrand = strings.TrimSpace(carBrand)
	carModel, _ := reader.ReadString('\n')
	carModel = strings.TrimSpace(carModel)

	// Motorraddetails lesen
	motoBrand, _ := reader.ReadString('\n')
	motoBrand = strings.TrimSpace(motoBrand)
	motoEngineStr, _ := reader.ReadString('\n')
	motoEngineStr = strings.TrimSpace(motoEngineStr)
	motoEngine, _ := strconv.Atoi(motoEngineStr)

	// Fahrraddetails lesen
	bicycleType, _ := reader.ReadString('\n')
	bicycleType = strings.TrimSpace(bicycleType)

	// TODO: Erstelle ein Car, Motorcycle und Bicycle mit den Eingabewerten

	// TODO: Rufe PrintDescription für jedes Fahrzeug auf, um Polymorphismus zu demonstrieren
	fmt.Println("TODO: Print vehicle descriptions")
}
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