Desafio Go
Composição com interfaces e sobrescrita
Enunciado
Crie uma interface Falante com o método Falar() string. Crie uma struct Animal que implementa Falar() retornando "Som genérico". Crie uma struct Gato que embuta Animal e sobrescreva Falar() retornando "Miau". No main, crie um slice de Falante contendo um Animal e um Gato, e imprima o resultado de Falar() para cada um.
Requisitos
- A interface
Falantedeve ter o métodoFalar() string. Animaldeve implementarFalar()retornando "Som genérico".Gatodeve embutirAnimale sobrescreverFalar()retornando "Miau".- O
maindeve iterar sobre um slice deFalantee imprimir os sons.
Código inicial
package main
import "fmt"
// Defina a interface e as structs aqui
func main() {
// Crie o slice e itere
}
Saída esperada
Som genérico
Miau
Ver dica
Para sobrescrever, defina um método Falar com receptor Gato. O método do Animal embutido será ocultado.
Mostrar solução
package main
import "fmt"
type Falante interface {
Falar() string
}
type Animal struct{}
func (a Animal) Falar() string {
return "Som genérico"
}
type Gato struct {
Animal // embedding
}
// Sobrescreve o método Falar do Animal
func (g Gato) Falar() string {
return "Miau"
}
func main() {
animais := []Falante{
Animal{},
Gato{},
}
for _, a := range animais {
fmt.Println(a.Falar())
}
}
Passo a passo
- Definimos a interface
Falantecom o métodoFalar() string. - Criamos
Animalcom o métodoFalarque retorna "Som genérico". - Criamos
GatoembutindoAnimal. - Definimos um método
Falarcom receptorGatoque retorna "Miau". Isso sobrescreve o método promovido. - No
main, criamos um slice deFalantecontendo umAnimale umGato. - Iteramos e chamamos
Falar()em cada elemento, imprimindo o resultado.
Por que funciona
O embedding promove o método Falar de Animal para Gato, mas como definimos um método com o mesmo nome em Gato, ele tem precedência. Assim, Gato satisfaz Falante com seu próprio método, enquanto Animal usa o seu. A interface permite tratar ambos polimorficamente.
Erros comuns
- Não sobrescrever corretamente: se o método em
Gatotiver receptor de ponteiro (*Gato), entãoGato{}(valor) não implementaráFalante; seria necessário usar&Gato{}. - Esquecer de embutir: se
Gatonão embutirAnimal, não herda o métodoFalare precisaria implementá-lo do zero. - Confundir interface com herança:
Gatonão é umAnimal; é um tipo que tem umAnimale pode sobrescrever métodos.
Outra forma de resolver
Poderia não usar embedding e simplesmente implementar Falar diretamente em Gato, mas perderia a reutilização de outros métodos de Animal.
Saída esperada
Som genérico
Miau