Direkt zum Hauptinhalt springen
eLearner.app
Modul 5 · Lektion 3 von 523/50 im Kurs~12 min
Lektionen des Moduls (3/5)

Komposition (Embedding)

Go hat keine Vererbung. Die idiomatische Antwort auf die Wiederverwendung lautet Zusammensetzung und insbesondere Einbettung: einschließlich eines Typs innerhalb eines anderen, ohne ihm einen Feldnamen zu geben. Die Bereiche und Methoden von Der eingebettete Typ wird heraufgestuft und wird so direkt zugänglich sie gehörten zum äußeren Typus.

Struktureinbettung

Go
type Animal struct {
    Name string
}

func (a Animal) Greet() string {
    return "ciao da " + a.Name
}

type Dog struct {
    Animal        // embedding — NO field name
    Breed string
}

c := Dog{
    Animal: Animal{Name: "Rex"},
    Breed:  "Pastore",
}

fmt.Println(c.Name)         // "Rex" — promoted from Animal
fmt.Println(c.Greet())      // "ciao da Rex" — promoted method
fmt.Println(c.Breed)        // own field

Das eingebettete Feld ist weiterhin über den Typnamen zugänglich: c.Animal.Name funktioniert und ist identisch mit c.Name. Es wird benötigt, wenn es kommt zu Kollisionen.

Override (teilweise): Methode „Shadowing“

Wenn der äußere Typ eine Methode mit demselben Namen wie die heraufgestufte definiert Erstens „gewinnt“ seine Methode. Von innen ist das Eingebettete jederzeit erreichbar eine über den Namen des Typs:

Go
func (c Dog) Greet() string {
    return "BAU! " + c.Animal.Greet()
}

Es handelt sich nicht um eine polymorphe Vererbung, sondern lediglich um eine lexikalische Namensauflösung. Für Polymorphismus verwenden Sie Schnittstellen (Modul 6).

Mehrfacheinbettung

Sie können mehrere Typen einbetten:

Go
type Logger struct{ /*...*/ }
func (l Logger) Log(msg string) { /*...*/ }

type Timer struct{ /*...*/ }
func (t Timer) Now() time.Time { /*...*/ }

type Service struct {
    Logger
    Timer
    Name string
}

s := Service{Name: "api"}
s.Log("start")   // promoted from Logger
s.Now()          // promoted from Timer

Wenn zwei eingebettete Typen eine Methode mit DEM GLEICHEN Namen haben, direkter Zugriff wird mehrdeutig und der Compiler benötigt die explizite Form (s.Logger.Foo() oder s.Timer.Foo()).

Schnittstelleneinbettung

Schnittstellen können auch „eingebettet“ werden (siehe Modul 6):

Go
type ReadWriter interface {
    io.Reader
    io.Writer
}

Es entspricht der Vereinigung der Methoden von Reader und Writer.

Wann sollte eine explizite Komposition verwendet werden (keine Einbettung)?

Wenn Sie ein benanntes Feld und keine automatische Heraufstufung wünschen, verwenden Sie „plain“. Zusammensetzung:

Go
type Dog struct {
    Anim  Animal    // NORMAL field, no promotion
    Breed string
}
c.Anim.Name   // you need the field name

Das Einbetten ist ein praktisches Delegierungstool, keine Designauswahl Grundsätzlich besser als eine explizite Komposition: Verwenden Sie sie, wenn Sie es wirklich wollen um die API des inneren Typs zu fördern.

Probieren Sie es aus

Übung#go.m5.l3.e1
Versuche: 0Wird geladen…

Definieren Sie „Hund“, der „Tier“ einbettet (Einbettung, kein Feldname) und über ein Rassenzeichenfolgenfeld verfügt.

Editor wird geladen…
Hinweis anzeigen

Einbettung: Schreiben Sie den TYP, ohne ihm einen Feldnamen zu geben.

Lösung nach 3 Versuchen verfügbar

Übung#go.m5.l3.e2
Versuche: 0Wird geladen…

Fügen Sie Animal eine Greet()-String-Methode hinzu und rufen Sie sie direkt für eine Dog-Variable auf (Methodenförderung).

Editor wird geladen…
Hinweis anzeigen

Die auf „Animal“ definierte Methode wird dank der Einbettung auf „Dog“ hochgestuft.

Lösung nach 3 Versuchen verfügbar

Quiz#go.m5.l3.e3
Bereit

Unterstützt Go die klassische Vererbung?

Go
type B struct { /* extends A? */ }
Antwortoptionen

Zusammenfassung

  • Keine Vererbung: Sie komponieren mit Einbettung.
  • Einbetten = Schreiben des TYPE ohne Feldnamen in die Struktur. – Felder und Methoden des eingebetteten Typs werden heraufgestuft.
  • Expliziter Zugriff ist immer verfügbar: outer.Inner.Field.
  • „Lexikalische“ Überschreibung: Die Methode des äußeren Typs überschattet die hochgestufte.
  • Einbettung ≠ is-a: Für Polymorphismus Schnittstellen verwenden.