Menu
Coddy logo textTech

Fondamenti dell'embedding delle struct

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 35 di 107.

L’incorporamento di struct è il meccanismo di Go per includere un tipo struct all’interno di un altro. Invece di usare un nome di campo, specifichi semplicemente il tipo e Go rende disponibili i campi della struct incorporata nella struct esterna.

Ecco la sintassi di base:

type Address struct {
    City    string
    Country string
}

type Person struct {
    Name string
    Address  // incorporato - senza nome del campo
}

Quando incorpori Address in Person, puoi accedere direttamente ai campi incorporati dalla struct esterna:

func main() {
    p := Person{
        Name: "Alice",
        Address: Address{
            City:    "London",
            Country: "UK",
        },
    }
    
    fmt.Println(p.City)     // London - acceso directo
    fmt.Println(p.Country)  // UK - acceso directo
    fmt.Println(p.Address.City)  // también funciona
}

Nota come p.City funziona senza scrivere esplicitamente p.Address.City. Go promuove automaticamente i campi della struct incorporata, rendendoli accessibili come se appartenessero alla struct esterna. Puoi comunque accedervi tramite il nome del tipo incorporato quando necessario.

Questo è diverso dalle normali struct annidate, in cui devi sempre usare il nome del campo per accedere ai campi interni. L'incorporamento crea un'API più piatta e comoda, mantenendo comunque il raggruppamento logico dei dati correlati.

challenge icon

Sfida

Facile

Costruiamo un sistema di registrazione dei veicoli che utilizza l'embedding delle struct per creare un modello dati ordinato e ben organizzato. Separerai le informazioni di contatto dai dettagli del veicolo, consentendo al contempo l'accesso diretto a tutti i campi tramite l'embedding.

Organizzerai il codice in due file:

  • vehicle.go: crea due struct che collaborano tramite l'embedding:
    • Una struct ContactInfo con i campi OwnerName e Phone (entrambi stringhe)
    • Una struct Vehicle che incorpora ContactInfo (senza un nome di campo) e aggiunge i propri campi Make, Model e Year
    Crea anche un metodo chiamato Summary su Vehicle che restituisca una stringa formattata contenente tutte le informazioni sul veicolo e sui contatti.
  • main.go: leggi i dettagli del veicolo e del proprietario dall'input, crea un'istanza di Vehicle con ContactInfo incorporata e mostra come accedere ai campi incorporati sia direttamente sia tramite il nome del tipo incorporato. Stampa il riepilogo del veicolo alla fine.

Verranno forniti i seguenti input:

  • Riga 1: nome del proprietario
  • Riga 2: numero di telefono
  • Riga 3: marca del veicolo
  • Riga 4: modello del veicolo
  • Riga 5: anno (intero)

Il tuo metodo Summary dovrebbe restituire una stringa nel seguente formato:

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

Nel file principale, mostra la promozione dei campi stampando:

  1. Il nome del proprietario, accedendovi direttamente tramite Vehicle (ad esempio, v.OwnerName)
  2. Il numero di telefono, accedendovi tramite il tipo incorporato (ad esempio, v.ContactInfo.Phone)
  3. Il riepilogo completo restituito dal tuo metodo Summary

Ad esempio, dati Alice Smith, 555-1234, Toyota, Camry e 2023, l'output dovrebbe essere:

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

Nota come funzionano entrambi i modi di accesso: l'accesso diretto tramite la promozione dei campi e l'accesso esplicito tramite il nome del tipo incorporato. Questo ti offre flessibilità nel lavorare con i dati incorporati.

Provalo tu

package main

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

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

	// Leggi il nome del proprietario
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)

	// Leggi il numero di telefono
	phone, _ := reader.ReadString('\n')
	phone = strings.TrimSpace(phone)

	// Leggi la marca del veicolo
	make, _ := reader.ReadString('\n')
	make = strings.TrimSpace(make)

	// Leggi il modello del veicolo
	model, _ := reader.ReadString('\n')
	model = strings.TrimSpace(model)

	// Leggi l'anno
	yearStr, _ := reader.ReadString('\n')
	yearStr = strings.TrimSpace(yearStr)
	year, _ := strconv.Atoi(yearStr)

	// TODO: Crea un'istanza di Vehicle con ContactInfo incorporato
	// Usa i valori letti dall'input qui sopra

	// TODO: Stampa il nome del proprietario accedendovi direttamente tramite Vehicle (promozione dei campi)
	// Esempio: fmt.Println(v.OwnerName)

	// TODO: Stampa il numero di telefono accedendovi tramite il nome del tipo incorporato
	// Esempio: fmt.Println(v.ContactInfo.Phone)

	// TODO: Stampa il riepilogo completo usando il metodo Summary
	// Esempio: fmt.Println(v.Summary())

	// Rimuovi queste righe dopo aver implementato la soluzione
	_ = ownerName
	_ = phone
	_ = make
	_ = model
	_ = year
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online