Chciałem rozwinąć odpowiedź udzieloną przez @jimt tutaj . Ta odpowiedź jest poprawna i ogromnie pomogła mi w rozwiązaniu tego problemu. Istnieją jednak pewne zastrzeżenia dotyczące obu metod (alias, embed), z którymi miałem problem.
uwaga : używam terminów rodzic i dziecko, chociaż nie jestem pewien, czy jest to najlepsze dla kompozycji. Zasadniczo rodzic to typ, który chcesz zmodyfikować lokalnie. Dziecko to nowy typ, który próbuje zaimplementować tę modyfikację.
Metoda 1 - Definicja typu
type child parent
type MyThing imported.Thing
- Zapewnia dostęp do pól.
- Nie zapewnia dostępu do metod.
type child struct {
parent
}
type MyThing struct {
*imported.Thing
}
- Zapewnia dostęp do pól.
- Zapewnia dostęp do metod.
- Wymaga rozważenia przy inicjalizacji.
Podsumowanie
- Używając metody kompozycji, osadzony rodzic nie zainicjuje się, jeśli jest wskaźnikiem. Rodzica musi zostać zainicjowany oddzielnie.
- Jeśli osadzony element nadrzędny jest wskaźnikiem i nie jest inicjowany podczas inicjowania elementu podrzędnego, wystąpi błąd wyłuskiwania wskaźnika zerowego.
- Zarówno definicja typu, jak i przypadki osadzania zapewniają dostęp do pól elementu nadrzędnego.
- Definicja typu nie pozwala na dostęp do metod rodzica, ale osadzenie rodzica tak.
Możesz to zobaczyć w poniższym kodzie.
przykład pracy na placu zabaw
package main
import (
"fmt"
)
type parent struct {
attr string
}
type childAlias parent
type childObjParent struct {
parent
}
type childPointerParent struct {
*parent
}
func (p *parent) parentDo(s string) { fmt.Println(s) }
func (c *childAlias) childAliasDo(s string) { fmt.Println(s) }
func (c *childObjParent) childObjParentDo(s string) { fmt.Println(s) }
func (c *childPointerParent) childPointerParentDo(s string) { fmt.Println(s) }
func main() {
p := &parent{"pAttr"}
c1 := &childAlias{"cAliasAttr"}
c2 := &childObjParent{}
c3 := &childPointerParent{}
c4 := &childPointerParent{&parent{}}
c2.attr = "cObjParentAttr"
c4.attr = "cPointerParentAttr"
fmt.Println(p.attr)
fmt.Println(c1.attr)
fmt.Println(c2.attr)
fmt.Println(c4.attr)
p.parentDo("called parentDo on parent")
c1.childAliasDo("called childAliasDo on ChildAlias")
c2.childObjParentDo("called childObjParentDo on ChildObjParent")
c3.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
c4.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
c2.parentDo("called parentDo on childObjParent")
c3.parentDo("called parentDo on childPointerParent")
c4.parentDo("called parentDo on childPointerParent")
}
“extension methods are not object-oriented”
) dla C #, ale patrząc na nie dzisiaj, od razu przypomniałem sobie o interfejsach Go (i jego podejściu do ponownego przemyślenia orientacji obiektowej), a potem miałem to pytanie.