Einführung in Interfaces
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 25 von 107.
Ein Interface in Go definiert eine Menge von Methodensignaturen, ohne diese zu implementieren. Es beschreibt, was ein Typ tun kann, nicht wie er es tut. Jeder Typ, der alle Methoden eines Interfaces implementiert, erfüllt dieses Interface automatisch.
So definieren Sie ein Interface:
type Speaker interface {
Speak() string
}Dieses Speaker-Interface erfordert, dass jeder implementierende Typ eine Speak()-Methode besitzt, die einen String zurückgibt. Nun kann jede Struktur mit dieser Methode überall dort verwendet werden, wo ein Speaker erwartet wird.
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return d.Name + " says woof!"
}
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return c.Name + " says meow!"
}Sowohl Dog als auch Cat erfüllen das Speaker-Interface, da sie jeweils über eine Speak()-Methode mit der korrekten Signatur verfügen. Sie können nun Funktionen schreiben, die jeden Speaker akzeptieren:
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
dog := Dog{Name: "Buddy"}
cat := Cat{Name: "Whiskers"}
MakeSound(dog) // Buddy says woof!
MakeSound(cat) // Whiskers says meow!
}Interfaces ermöglichen es Ihnen, flexiblen, wiederverwendbaren Code zu schreiben, der mit jedem Typ funktioniert, der die Anforderungen des Interfaces erfüllt, unabhängig von der zugrunde liegenden Implementierung.
Aufgabe
EinfachLassen Sie uns ein Fahrzeugbeschreibungssystem erstellen, das zeigt, wie Interfaces es verschiedenen Typen ermöglichen, gemeinsames Verhalten zu teilen. Sie werden ein Interface erstellen, das mehrere Fahrzeugtypen erfüllen können, und es dann verwenden, um jedes Fahrzeug einheitlich zu beschreiben.
Sie werden Ihren Code auf zwei Dateien aufteilen:
vehicles.go: Definieren Sie einDescriber-Interface mit einer einzelnen MethodeDescribe() string. Erstellen Sie dann zwei Structs, die dieses Interface erfüllen:Carmit den FeldernBrandundModel(beides Strings)Bicyclemit den FeldernType(String) undGears(int)
Describe()-Methode haben, die einen beschreibenden String über das Fahrzeug zurückgibt.main.go: Erstellen Sie eine Funktion namensPrintDescription, die jedenDescriberakzeptiert und das Ergebnis des Aufrufs seinerDescribe()-Methode ausgibt. Lesen Sie Fahrzeuginformationen aus der Eingabe ein, erstellen Sie sowohl ein Car als auch ein Bicycle und verwenden Sie Ihre Funktion, um Beschreibungen für jedes Fahrzeug auszugeben.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Automarke
- Zeile 2: Automodell
- Zeile 3: Fahrradtyp
- Zeile 4: Anzahl der Gänge (Ganzzahl)
Ihre Describe()-Methoden sollten Strings in diesen Formaten zurückgeben:
- Car:
[Brand] [Model] - Bicycle:
[Type] bike with [Gears] gears
Zum Beispiel, gegeben Toyota, Camry, Mountain und 21, sollte Ihre Ausgabe wie folgt aussehen:
Toyota Camry
Mountain bike with 21 gearsDie entscheidende Erkenntnis ist, dass Ihre PrintDescription-Funktion mit jedem Typ funktioniert, der eine Describe()-Methode besitzt – sie muss nicht wissen, ob es sich um ein Car, ein Bicycle oder einen anderen Fahrzeugtyp handelt, den Sie später hinzufügen könnten.
Spickzettel
Ein Interface in Go definiert eine Menge von Methodensignaturen, ohne diese zu implementieren. Jeder Typ, der alle Methoden implementiert, erfüllt dieses Interface automatisch.
Definieren eines Interfaces:
type Speaker interface {
Speak() string
}Typen, die die erforderlichen Methoden implementieren, erfüllen das Interface:
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return d.Name + " says woof!"
}
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return c.Name + " says meow!"
}Funktionen können jeden Typ akzeptieren, der das Interface erfüllt:
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
dog := Dog{Name: "Buddy"}
cat := Cat{Name: "Whiskers"}
MakeSound(dog) // Buddy sagt wuff!
MakeSound(cat) // Whiskers sagt miau!
}Probier es selbst
package main
import (
"fmt"
)
// TODO: Erstellen Sie eine PrintDescription-Funktion, die jeden Describer akzeptiert
// und das Ergebnis des Aufrufs seiner Describe()-Methode ausgibt
func main() {
// Eingabe lesen
var carBrand string
var carModel string
var bicycleType string
var gears int
fmt.Scanln(&carBrand)
fmt.Scanln(&carModel)
fmt.Scanln(&bicycleType)
fmt.Scanln(&gears)
// TODO: Erstellen Sie ein Car mit der Marke und dem Modell aus der Eingabe
// TODO: Erstellen Sie ein Bicycle mit dem Typ und den Gängen aus der Eingabe
// TODO: Verwenden Sie PrintDescription, um die Beschreibung des Autos auszugeben
// TODO: Verwenden Sie PrintDescription, um die Beschreibung des Fahrrads auszugeben
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool