Garantindo que estruturas incorporadas implementem a interface sem introduzir ambiguidade
Estou tentando limpar minha base de código, fazendo um melhor trabalho ao definir interfaces e usando estruturas incorporadas para reutilizar a funcionalidade. No meu caso, tenho muitos tipos de entidades que podem ser vinculados a vários objetos. Quero definir interfaces que capturem os requisitos e estruturas que implementam as interfaces que podem ser incorporadas às entidades.
// All entities implement this interface
type Entity interface {
Identifier()
Type()
}
// Interface for entities that can link Foos
type FooLinker interface {
LinkFoo()
}
type FooLinkerEntity struct {
Foo []*Foo
}
func (f *FooLinkerEntity) LinkFoo() {
// Issue: Need to access Identifier() and Type() here
// but FooLinkerEntity doesn't implement Entity
}
// Interface for entities that can link Bars
type BarLinker interface {
LinkBar()
}
type BarLinkerEntity struct {
Bar []*Bar
}
func (b *BarLinkerEntity) LinkBar() {
// Issues: Need to access Identifier() and Type() here
// but BarLinkerEntity doesn't implement Entity
}
Então, meu primeiro pensamento foi ter FooLinkerEntity e BarLinkerEntity apenas implementando a interface Entity.
// Implementation of Entity interface
type EntityModel struct {
Id string
Object string
}
func (e *EntityModel) Identifier() { return e.Id }
func (e *EntityModel) Type() { return e.Type }
type FooLinkerEntity struct {
EntityModel
Foo []*Foo
}
type BarLinkerEntity struct {
EntityModel
Bar []*Bar
}
No entanto, isso acaba com um erro de ambiguidade para todos os tipos que podem vincular Foos e Bars.
// Baz.Identifier() is ambiguous between EntityModel, FooLinkerEntity,
// and BarLinkerEntity.
type Baz struct {
EntityModel
FooLinkerEntity
BarLinkerEntity
}
Qual é a maneira correta de estruturar esse tipo de código? Eu apenas faço uma asserção de tipo noLinkFoo()
eLinkBar()
chegar aIdentifier()
eType()
? Existe alguma maneira de obter essa verificação no tempo de compilação, em vez do tempo de execução?