Menu
Coddy logo textTech

Nascondimento delle informazioni in Go

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

L'occultamento delle informazioni va oltre il semplice rendere i campi non esportati. Si tratta di progettare i tuoi tipi in modo che il codice esterno conosca solo ciò che deve sapere. Nient'altro.

L'obiettivo è esporre il comportamento tramite i metodi, mantenendo completamente nascosta la struttura interna. Considera questo approccio:

type Counter struct {
    value    int
    maxLimit int
}

func NewCounter(limit int) *Counter {
    return &Counter{maxLimit: limit}
}

func (c *Counter) Increment() bool {
    if c.value >= c.maxLimit {
        return false
    }
    c.value++
    return true
}

func (c *Counter) Value() int {
    return c.value
}

Il codice esterno non sa che Counter usa internamente un int. Potrebbe essere un float64, una slice o qualcos'altro. L'implementazione può cambiare senza influire sul codice che usa Counter, purché i metodi si comportino allo stesso modo.

Questo principio si applica anche alle funzioni di supporto. Mantieni la logica interna non esportata:

// Esportato - parte dell'API pubblica
func (c *Counter) Reset() {
    c.value = 0
}

// non esportato - funzione ausiliaria interna
func (c *Counter) isAtLimit() bool {
    return c.value >= c.maxLimit
}

Nascondendo isAtLimit(), sei libero di modificarla o rimuoverla in seguito. L'incapsulamento delle informazioni crea un confine chiaro tra ciò che il tuo pacchetto promette agli utenti esterni e il suo funzionamento interno.

challenge icon

Sfida

Facile

Costruiamo un sistema di portafoglio sicuro che dimostri l'incapsulamento delle informazioni. Creerai un portafoglio digitale in cui il saldo interno e la cronologia delle transazioni sono completamente nascosti al codice esterno: viene esposto solo il comportamento tramite metodi.

Organizzerai il codice in due file:

  • wallet.go: crea una struct Wallet che nasconde tutto il suo stato interno. Il portafoglio dovrebbe tenere traccia internamente del saldo attuale e di un limite di spesa, ma il codice esterno non dovrebbe mai sapere come questi dati sono memorizzati o rappresentati. Esponi il comportamento tramite questi metodi:
    • NewWallet(limit float64) *Wallet - costruttore che crea un portafoglio con il limite di spesa indicato e saldo pari a zero
    • Deposit(amount float64) bool - aggiunge denaro al portafoglio, restituisce true se l'operazione riesce (l'importo deve essere positivo)
    • Spend(amount float64) bool - preleva denaro se il saldo è sufficiente E l'importo non supera il limite di spesa, restituisce true se l'operazione riesce
    • Balance() float64 - restituisce il saldo attuale
    • Status() string - restituisce un messaggio di stato nel formato: Balance: $[balance] (Limit: $[limit])
    Mantieni tutta la logica di supporto (come il controllo della validità di una transazione) in funzioni o metodi non esportati. Si tratta di dettagli interni dell'implementazione che potrebbero cambiare in seguito.
  • main.go: leggi dalla casella di input la configurazione del portafoglio e le transazioni, crea un portafoglio, esegui le operazioni e mostra i risultati dopo ogni azione.

Verranno forniti i seguenti input:

  • Riga 1: limite di spesa
  • Riga 2: importo del deposito
  • Riga 3: importo della prima spesa
  • Riga 4: importo della seconda spesa

Dopo aver creato il portafoglio, stampa il suo stato iniziale. Poi esegui ciascuna operazione e stampa lo stato aggiornato (se riesce) oppure Transaction failed (se l'operazione viene rifiutata). Formatta tutti gli importi in dollari con due cifre decimali.

Per esempio, dati 50, 100, 30 e 80, l'output dovrebbe essere:

Balance: $0.00 (Limit: $50.00)
Balance: $100.00 (Limit: $50.00)
Balance: $70.00 (Limit: $50.00)
Transaction failed

L'ultima transazione non riesce perché $80 supera il limite di spesa di $50, anche se il saldo è sufficiente. Il portafoglio applica internamente le proprie regole senza esporre come prende queste decisioni. Il codice esterno si limita a chiamare i metodi e a ricevere i risultati, senza conoscere i dettagli interni dell'implementazione.

Provalo tu

package main

import (
	"fmt"
)

func main() {
	// Leggi i dati di input
	var limit float64
	var depositAmount float64
	var spend1 float64
	var spend2 float64

	fmt.Scanln(&limit)
	fmt.Scanln(&depositAmount)
	fmt.Scanln(&spend1)
	fmt.Scanln(&spend2)

	// TODO: Crea un nuovo portafoglio con il limite di spesa indicato

	// TODO: Stampa lo stato iniziale

	// TODO: Effettua il deposito e stampa il risultato (stato o "Transaction failed")

	// TODO: Effettua la prima spesa e stampa il risultato

	// TODO: Effettua la seconda spesa e stampa il risultato
}
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