Lektionen des Moduls (1/5)
Interfaces: Verhalten definieren
Eine Schnittstelle in Go ist ein Satz von Methodensignaturen. Ein Wert
implementiert die Schnittstelle, wenn sie alle dieser Methoden hat – nein
implements, kein extends, keine explizite Registrierung. Es ist das
Modell, das oft als „strukturelle Typisierung“ oder „statische Ententypisierung“ bezeichnet wird:
Der Compiler prüft die Konformität zur Kompilierungszeit, jedoch basierend auf
Form, nicht auf Deklarationen.
Eine Schnittstelle deklarieren
type Greeter interface {
Greet() string
}Konvention: Namen, die auf -er enden, für Einzelmethodenschnittstellen
(Reader, Writer, Stringer, Closer). Kleine Schnittstellen
(1–2 Methoden) sind idiomatisch: Die Standardbibliothek ist voll davon
winzige Schnittstellen, die sich zusammensetzen (io.ReadWriter,
io.ReadCloser, …).
Implizite Implementierung
type Person struct{ Name string }
func (p Person) Greet() string {
return "ciao " + p.Name
}
// Person satisfies Greeter because it has the required method.
var s Greeter = Person{Name: "Ada"}
fmt.Println(s.Greet())Kein Schlüsselwort. Wenn der Typ über die Methoden verfügt, kann er zugewiesen werden eine Variable dieses Schnittstellentyps. Das ist es.
Polymorphismus über Schnittstelle
type Robot struct{ ID string }
func (r Robot) Greet() string { return "bip " + r.ID }
func greet(s Greeter) {
fmt.Println(s.Greet())
}
greet(Person{Name: "Ada"})
greet(Robot{ID: "R2"})greet akzeptiert jeden Typ, der Greeter erfüllt. Das ist der Go-Weg
des Polymorphismus: keine Hierarchien, nur Fähigkeiten.
Die leere Schnittstelle
var x interface{} = 42
var y any = "ciao" // any is the built-in alias of interface{}interface{} (oder any seit Go 1.18) erfordert keine Methoden, also welche
Wert befriedigt es. Nützlich für generische Container, aber zum Extrahieren
Für den konkreten Wert benötigen Sie eine Typzusicherung oder einen Typschalter
(nächste Lektionen).
Methodensatz: Wert vs. Zeigerempfänger (Vorschau)
Rückruf aus Modul 5:
- Methoden mit einem Wertempfänger befinden sich im Methodensatz von
Tund*T. - Methoden mit einem Zeigerempfänger sind NUR im Methodensatz von
*Tenthalten.
Praktische Konsequenz:
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }
type Incrementer interface { Inc() }
var i Incrementer = &Counter{} // OK: *Counter has Inc()
// var j Incrementer = Counter{} // ERROR: Counter (value) does NOTWenn eine Methode einen Zeigerempfänger hat, müssen Sie ihm einen Zeiger zuweisen die Schnittstellenvariable.
Probieren Sie es aus
Definieren Sie einen Schnittstellen-Greeter mit einer einzigen Greet()-Methodenzeichenfolge.
Hinweis anzeigen
Syntax: `type Name interface { Method(args) return }`.
Lösung nach 3 Versuchen verfügbar
Implementieren Sie Greeter auf einem neuen Robotertyp mit Feld-ID-Zeichenfolge. Die Methode gibt „bip“ + ID zurück.
Hinweis anzeigen
Kein `implements`: Definieren Sie einfach die Methode mit der richtigen Signatur.
Lösung nach 3 Versuchen verfügbar
Wie deklarieren Sie, dass Typ P die Greeter-Schnittstelle implementiert?
type P struct{}
// ?Zusammenfassung
- Schnittstelle = Satz von Methodensignaturen; kein
implements. - Implizite Implementierung: Es müssen nur die Methoden mit der richtigen Signatur vorhanden sein.
- Idiomatisch: kleine Schnittstellen (1–2 Methoden), Namen in
-er. interface{}/any: akzeptiert jeden Wert, verliert die Typsicherheit.- Methodensatz: Zeigerempfänger → nur
*Terfüllt die Schnittstelle. - Go-Polymorphismus: schnittstellentypisierte Parameter, keine Hierarchien.