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
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 fieldGö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:
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:
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):
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:
type Dog struct {
Anim Animal // NORMAL field, no promotion
Breed string
}
c.Anim.Name // you need the field nameGö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
Animal'ı içeren (gömme, alan adı olmayan) ve Breed dize alanına sahip olan Dog'u tanımlayın.
İpucu göster
Gömme: TYPE'ı alan adı vermeden yazın.
3 denemeden sonra çözüm mevcut
Animal'a bir Greet() dize yöntemi ekleyin ve onu doğrudan bir Dog değişkeninde çağırın (yöntem yükseltme).
İpucu göster
Animal üzerinde tanımlanan yöntem, embed sayesinde Dog’a aktarılır.
3 denemeden sonra çözüm mevcut
Go klasik mirası destekliyor mu?
type B struct { /* extends A? */ }Ö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.