Go-Vererbung
In der objektorientierten Programmierung (OOP) ist Vererbung ein Mechanismus, der es einer Klasse (Unterklasse) ermöglicht, Attribute und Methoden von einer anderen Klasse (Oberklasse) zu erben. Durch Vererbung können Unterklassen den Code der Oberklasse wiederverwenden und ihr Verhalten erweitern oder ändern, ohne die Oberklasse zu ändern.
Go ist keine traditionelle objektorientierte Programmiersprache; es besitzt keine Klassen oder Vererbung.
Go verwendet Structs und Interfaces, um ähnliche Funktionalität zu implementieren.
"Vererbung" in Go
Die Sprache Go kennt keine Klassen- und Vererbungskonzepte, wie sie in traditionellen objektorientierten Sprachen zu finden sind; stattdessen verwendet sie Komposition und Interfaces, um ähnliche Funktionalität zu erreichen.
Composition
Komposition ist der primäre Weg, wie Go Code-Wiederverwendung implementiert. Durch das Einbetten eines Structs in ein anderes kann das untergeordnete Struct die Felder und Methoden des übergeordneten Structs "erben".
Beispiel
import "fmt"
// Eltern-Struct
type Animal struct {
Name string
}
// Methode des Eltern-Structs
func (a *Animal) Speak() {
fmt.Println(a.Name, "says hello!")
}
// Kind-Struct
type Dog struct {
Animal // Animal-Struct einbetten
Breed string
}
func main() {
dog := Dog{
Animal: Animal{Name: "Buddy"},
Breed: "Golden Retriever",
}
dog.Speak() // Methode der übergeordneten Struktur aufrufen
fmt.Println("Breed:", dog.Breed)
}
Code-Erklärung
Animalist die übergeordnete Struktur, die ein Feld enthältNameund eine MethodeSpeak。Dogist die untergeordnete Struktur durch EinbettungAnimalDie Struktur erbtAnimaldie Felder und Methoden von.- In
mainIn der Funktion haben wir eineDogeine Instanz, und riefen aufSpeakMethode.
2. Schnittstelle
Schnittstellen sind der primäre Weg, wie Go Polymorphismus implementiert. Durch die Definition von Schnittstellen können verschiedene Strukturen dieselben Methoden implementieren und dadurch ein polymorphes Verhalten ähnlich der Vererbung erreichen.
Beispielcode
Beispiel
import "fmt"
// Schnittstelle definieren
type Speaker interface {
Speak()
}
// Eltern-Struct
type Animal struct {
Name string
}
// Methoden der Schnittstelle implementieren
func (a *Animal) Speak() {
fmt.Println(a.Name, "says hello!")
}
// Kind-Struct
type Dog struct {
Animal
Breed string
}
func main() {
var speaker Speaker
dog := Dog{
Animal: Animal{Name: "Buddy"},
Breed: "Golden Retriever",
}
speaker = &dog
speaker.Speak() // Die Methode über die Schnittstelle aufrufen
}
Code-Erklärung
Speakerist eine Schnittstelle, die eineSpeakMethode.AnimalDie Struktur implementiertSpeakerSchnittstelle.DogDas Struct, durch Einbettung,AnimalStruct, das indirekt implementiertSpeakerSchnittstelle.- In
mainIn der Funktion werden wirDogdie Instanz zuweisen anSpeakerInterface, und über das Interface aufgerufenSpeakMethode.
Unterschiede zwischen Go und klassischer Vererbung
| Funktionen | Klassische Vererbung | der Go-Weg |
|---|---|---|
| Code-Wiederverwendung | Durch Vererbung | Durch Komposition (Einbetten von Structs) |
| Polymorphismus | Durch Vererbung und Methodenüberschreibung | durch Interfaces implementiert |
| Beziehung | "Ist-ein"-Beziehung | "Hat-ein"- oder "implementiert"-Beziehung. |
| Flexibilität | Die Vererbungsbeziehung ist fest | kann zur Laufzeit zusammengesetzt werden |
Vollständige Vererbungssimulation:
Beispiel
import "fmt"
// Basisklasse
type Vehicle struct {
Brand string
}
func (v *Vehicle) Start() {
fmt.Println(v.Brand, "started")
}
// Abgeleitete Klasse
type Car struct {
Vehicle // Vehicle einbetten
Model string
}
// Start-Methode überschreiben
func (c *Car) Start() {
fmt.Println(c.Brand, c.Model, "Auto gestartet")
}
func main() {
v := Vehicle{Brand: "Toyota"}
c := Car{
Vehicle: Vehicle{Brand: "Honda"},
Model: "Civic",
}
v.Start() // Toyota gestartet
c.Start() // Honda Civic Auto gestartet
c.Vehicle.Start() // Honda gestartet
}
Dieses Design in Go vermeidet viele Probleme der traditionellen Vererbung, wie das Problem der fragilen Basisklasse, und bietet gleichzeitig größere Flexibilität.
Weitere Erweiterungen