Menu
Coddy logo textTech

Noções básicas de incorporação de structs

Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 35 de 107.

Incorporação de structs é o mecanismo do Go para incluir um tipo struct dentro de outro. Em vez de usar um nome de campo, você simplesmente especifica o tipo, e o Go promove os campos da struct incorporada para a struct externa.

Aqui está a sintaxe básica:

type Address struct {
    City    string
    Country string
}

type Person struct {
    Name string
    Address  // embutido - sem nome de campo
}

Quando você incorpora Address em Person, pode acessar os campos incorporados diretamente na struct externa:

func main() {
    p := Person{
        Name: "Alice",
        Address: Address{
            City:    "London",
            Country: "UK",
        },
    }
    
    fmt.Println(p.City)     // London - acesso direto
    fmt.Println(p.Country)  // UK - acesso direto
    fmt.Println(p.Address.City)  // também funciona
}

Observe como p.City funciona sem escrever explicitamente p.Address.City. O Go promove automaticamente os campos da struct incorporada, tornando-os acessíveis como se pertencessem à struct externa. Você ainda pode acessá-los por meio do nome do tipo incorporado quando necessário.

Isso difere das estruturas aninhadas comuns, nas quais você sempre precisa usar o nome do campo para acessar os campos internos. A incorporação cria uma API mais plana e conveniente, mantendo ainda o agrupamento lógico de dados relacionados.

challenge icon

Desafio

Fácil

Vamos criar um sistema de registro de veículos que usa incorporação de structs para criar um modelo de dados limpo e organizado. Você separará as informações de contato dos detalhes do veículo, permitindo acesso direto a todos os campos por meio da incorporação.

Você organizará seu código em dois arquivos:

  • vehicle.go: Crie duas structs que trabalham juntas por meio da incorporação:
    • Uma struct ContactInfo com os campos OwnerName e Phone (ambos strings)
    • Uma struct Vehicle que incorpora ContactInfo (sem um nome de campo) e adiciona seus próprios campos Make, Model e Year
    Crie também um método chamado Summary em Vehicle que retorne uma string formatada contendo todas as informações do veículo e do contato.
  • main.go: Leia os detalhes do veículo e do proprietário da entrada, crie uma instância de Vehicle com ContactInfo incorporada e demonstre o acesso aos campos incorporados tanto diretamente quanto por meio do nome do tipo incorporado. Imprima o resumo do veículo ao final.

As seguintes entradas serão fornecidas:

  • Linha 1: Nome do proprietário
  • Linha 2: Número de telefone
  • Linha 3: Marca do veículo
  • Linha 4: Modelo do veículo
  • Linha 5: Ano (inteiro)

Seu método Summary deve retornar uma string neste formato:

[Year] [Make] [Model] - Owner: [OwnerName], Phone: [Phone]

Em seu arquivo principal, demonstre a promoção de campos imprimindo:

  1. O nome do proprietário acessado diretamente em Vehicle (por exemplo, v.OwnerName)
  2. O telefone acessado por meio do tipo incorporado (por exemplo, v.ContactInfo.Phone)
  3. O resumo completo do seu método Summary

Por exemplo, considerando Alice Smith, 555-1234, Toyota, Camry e 2023, sua saída deve ser:

Alice Smith
555-1234
2023 Toyota Camry - Owner: Alice Smith, Phone: 555-1234

Observe como os dois padrões de acesso funcionam: o acesso direto por meio da promoção de campos e o acesso explícito por meio do nome do tipo incorporado, oferecendo flexibilidade na forma como você trabalha com dados incorporados.

Experimente você mesmo

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Ler o nome do proprietário
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)

	// Ler o número de telefone
	phone, _ := reader.ReadString('\n')
	phone = strings.TrimSpace(phone)

	// Ler a marca do veículo
	make, _ := reader.ReadString('\n')
	make = strings.TrimSpace(make)

	// Ler o modelo do veículo
	model, _ := reader.ReadString('\n')
	model = strings.TrimSpace(model)

	// Ler o ano
	yearStr, _ := reader.ReadString('\n')
	yearStr = strings.TrimSpace(yearStr)
	year, _ := strconv.Atoi(yearStr)

	// TODO: Crie uma instância de Vehicle com ContactInfo embutido
	// Use os valores lidos da entrada acima

	// TODO: Imprima o nome do proprietário acessado diretamente no Vehicle (promoção de campo)
	// Exemplo: fmt.Println(v.OwnerName)

	// TODO: Imprima o telefone acessado através do nome do tipo embutido
	// Exemplo: fmt.Println(v.ContactInfo.Phone)

	// TODO: Imprima o resumo completo usando o método Summary
	// Exemplo: fmt.Println(v.Summary())

	// Remova estas linhas assim que implementar a solução
	_ = ownerName
	_ = phone
	_ = make
	_ = model
	_ = year
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Go online