Desafio Go
Formas geométricas com interface
Enunciado
Crie uma interface Forma com o método Area() float64. Implemente os tipos Retangulo (campos largura, altura float64) e Circulo (campo raio float64). Use receiver de valor para Area. No main, crie um slice de Forma com um retângulo e um círculo, e imprima a área de cada um.
Requisitos
- Interface
FormacomArea() float64 RetanguloeCirculoimplementamFormacom receiver de valor- Slice
[]Formacontendo ambas as formas - Imprimir a área de cada forma com
fmt.Printf
Código inicial
package main
import (
"fmt"
"math"
)
type Forma interface {
Area() float64
}
// TODO: defina Retangulo e Circulo com Area()
func main() {
// TODO: crie slice de Forma e imprima as áreas
}
Saída esperada
Retângulo: 24.00
Círculo: 78.54
Ver dica
Para o círculo, use math.Pi * raio * raio. O receiver de valor é suficiente porque só lemos campos.
Mostrar solução
package main
import (
"fmt"
"math"
)
type Forma interface {
Area() float64
}
type Retangulo struct {
largura, altura float64
}
// Receiver de valor: lê os campos sem modificar.
func (r Retangulo) Area() float64 {
return r.largura * r.altura
}
type Circulo struct {
raio float64
}
// Receiver de valor: lê o campo raio.
func (c Circulo) Area() float64 {
return math.Pi * c.raio * c.raio
}
func main() {
formas := []Forma{
Retangulo{largura: 6, altura: 4},
Circulo{raio: 5},
}
fmt.Printf("Retângulo: %.2f\n", formas[0].Area())
fmt.Printf("Círculo: %.2f\n", formas[1].Area())
}
Passo a passo
- Declaramos a interface
Formacom o métodoArea() float64. - Definimos
Retangulocom camposlarguraealtura. - Implementamos
Areacom receiver de valor(r Retangulo), multiplicando os campos. - Definimos
Circulocom camporaio. - Implementamos
Areacom receiver de valor(c Circulo), usandomath.Pi * c.raio * c.raio. - No
main, criamos um slice[]Formacom umRetanguloe umCirculo. - Imprimimos as áreas com
fmt.Printfe formato%.2f.
Por que funciona
Como Area tem receiver de valor, tanto Retangulo quanto Circulo (valores) satisfazem a interface Forma. O method set de Retangulo inclui Area, então Retangulo{...} pode ser atribuído a Forma. O slice armazena valores que implementam a interface, e a chamada formas[i].Area() é resolvida dinamicamente.
Erros comuns
- Usar receiver de ponteiro em
Areae tentar atribuir valor aForma:Retangulo{...}não implementaFormaseAreaforfunc (r *Retangulo) Area(). Seria necessário usar&Retangulo{...}. - Esquecer de importar
math: erro de compilação ao usarmath.Pi. - Formatar com
%dem vez de%.2f: saída incorreta ou erro de formatação.
Outra forma de resolver
Poderia usar receiver de ponteiro e armazenar ponteiros no slice: []Forma{&Retangulo{...}, &Circulo{...}}. Isso é preferível se os métodos precisarem modificar o estado ou se os structs forem grandes.
Saída esperada
Retângulo: 24.00
Círculo: 78.54