Ana içeriğe geç
Modül 5 · Ders 3 ders 5Kurstaki 23/50~12 min
Modül dersleri (3/5)

Kompozisyon (yerleştirme)

Go mirası yoktur. Yeniden kullanmanın deyimsel cevabı: bileşim ve özellikle yerleştirme: bir tür dahil bir alan adı vermeden bir başkasının içine. Alanları ve yöntemleri gömülü tür terfi ettirilir ve sanki doğrudan erişilebilir hale gelir onlar dış tipe aitti.

Yapı yerleştirme

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

Gömülü alana türün adıyla hâlâ erişilebilir: c.Animal.Name çalışır ve c.Name ile aynıdır. Ne zaman ihtiyaç duyulur çarpışmalar var.

Geçersiz kıl (kısmi): "gölgeleme" yöntemi

Dış tür, tanıtılanla aynı adı taşıyan bir yöntemi tanımlıyorsa Birincisi, yöntemi "kazanır". İçeriden her zaman gömülü olana ulaşabilirsiniz. türün adı aracılığıyla bir tane:

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

Bu polimorfik kalıtım değildir: yalnızca sözcüksel ad çözümlemesidir. Polimorfizm için arayüzler (Modül 6) kullanırsınız.

Çoklu yerleştirme

Birden fazla tür gömebilirsiniz:

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

İki gömülü türün AYNI ada sahip bir yöntemi varsa, doğrudan erişim belirsiz hale gelir ve derleyici açık formu gerektirir (s.Logger.Foo() veya s.Timer.Foo()).

Arayüz yerleştirme

Arayüzler aynı zamanda "gömülü" de olabilir (bkz. Modül 6):

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

Reader ve Writer yöntemlerinin birleşimine eşdeğerdir.

Açık kompozisyon ne zaman kullanılmalı (gömme değil)

Adlandırılmış bir alan istiyorsanız ve otomatik tanıtım istemiyorsanız, düz kullanın kompozisyon:

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

Gömme kullanışlı bir delegasyon aracıdır, bir tasarım seçeneği değildir açık kompozisyondan kesinlikle daha iyidir: gerçekten istediğiniz zaman kullanın iç türün API'sini tanıtmak için.

Deneyin

Egzersiz#go.m5.l3.e1
Denemeler: 0Yükleniyor…

Animal'ı içeren (gömme, alan adı olmayan) ve Breed dize alanına sahip olan Dog'u tanımlayın.

Düzenleyici yükleniyor…
İpucu göster

Gömme: TYPE'ı alan adı vermeden yazın.

3 denemeden sonra çözüm mevcut

Egzersiz#go.m5.l3.e2
Denemeler: 0Yükleniyor…

Animal'a bir Greet() dize yöntemi ekleyin ve onu doğrudan bir Dog değişkeninde çağırın (yöntem yükseltme).

Düzenleyici yükleniyor…
İpucu göster

Animal üzerinde tanımlanan yöntem, embed sayesinde Dog’a aktarılır.

3 denemeden sonra çözüm mevcut

Quiz#go.m5.l3.e3
Hazır

Go klasik mirası destekliyor mu?

Go
type B struct { /* extends A? */ }
Cevap seçenekleri

Özet

  • Miras yok: yerleştirme ile oluşturursunuz.
  • Gömme = TYPE'ın yapıda alan adı olmadan yazılması.
  • Gömülü türdeki alanlar ve yöntemler tanıtılır.
  • Açık erişim her zaman mevcuttur: outer.Inner.Field.
  • "Sözcüksel" geçersiz kılma: dış türün yöntemi yükseltilen yöntemi gölgeler.
  • Gömme ≠ is-a: polimorfizm için arayüzler kullanın.