Metodi Getter e Setter
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 49 di 107.
Poiché i campi non esportati non possono essere acceduti direttamente dall'esterno di un pacchetto, devi fornire metodi che consentano un accesso controllato. Questi sono comunemente chiamati getter e setter.
In Go, la convenzione per i getter è semplice: usa il nome del campo con la prima lettera maiuscola. Non aggiungere il prefisso "Get", usa semplicemente Balance(), non GetBalance():
type BankAccount struct {
balance int // non esportato
}
// Getter - restituisce il valore
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - modifica il valore con una convalida
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
Il vero potere dei setter consiste nell’aggiungere convalide o logica di business. Invece di consentire al codice esterno di impostare direttamente qualsiasi valore, controlli cosa è consentito:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
Questo metodo Deposit agisce come un setter specializzato che impone delle regole: non sono ammessi depositi negativi. Il codice esterno deve passare attraverso i tuoi metodi, assicurando che la struct rimanga sempre in uno stato valido. Questa è l’incapsulazione in azione: nascondere i dati esponendo al contempo un comportamento controllato.
Sfida
FacileCostruiamo un convertitore di temperatura che dimostri il corretto incapsulamento usando metodi getter e setter. Creerai una struct che memorizza internamente la temperatura in Celsius, ma ne consente l'accesso controllato tramite metodi con convalida.
Organizzerai il codice in due file:
temperature.go: crea una structTemperaturecon un campocelsiusnon esportato (float64). Implementa i seguenti metodi:Celsius()- un getter che restituisce la temperatura attuale in CelsiusSetCelsius(value float64)- un setter che accetta solo valori pari o superiori allo zero assoluto (-273.15). Se il valore è inferiore a questa soglia, la temperatura deve rimanere invariata.Fahrenheit()- restituisce la temperatura convertita in Fahrenheit usando la formula:(celsius * 9/5) + 32SetFahrenheit(value float64)- converte l'input da Fahrenheit a Celsius e lo memorizza, ma solo se il valore Celsius risultante è pari o superiore a -273.15
NewTemperature(celsius float64) *Temperatureche crea una temperatura inizializzata al valore specificato (assumi che l'input del costruttore sia valido).main.go: leggi i valori della temperatura dall'input e mostra i metodi getter/setter. Crea una temperatura, visualizzane i valori in entrambe le unità, poi prova a impostare nuovi valori e mostra i risultati.
Verranno forniti i seguenti input:
- Riga 1: valore iniziale in Celsius
- Riga 2: nuovo valore Celsius da impostare
- Riga 3: nuovo valore Fahrenheit da impostare
Formatta tutti i valori di temperatura con due cifre decimali. Stampa la seguente sequenza:
- Dopo la creazione:
C: [celsius] F: [fahrenheit] - Dopo aver impostato Celsius:
C: [celsius] F: [fahrenheit] - Dopo aver impostato Fahrenheit:
C: [celsius] F: [fahrenheit]
Per esempio, dati 25, -300 e 212, l'output dovrebbe essere:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Nota che la seconda riga mostra valori invariati perché -300 è inferiore allo zero assoluto, quindi il setter lo ha rifiutato. La terza riga mostra la temperatura dopo aver impostato con successo 212°F (che viene convertito in 100°C). Questa è la potenza dei setter: applicano regole che mantengono validi i dati.
Provalo tu
package main
import (
"fmt"
)
func main() {
// Leggi i valori di input
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Crea un nuovo oggetto Temperature usando il costruttore
// TODO: Stampa i valori iniziali nel formato "C: [celsius] F: [fahrenheit]" con 2 cifre decimali
// TODO: Prova a impostare il nuovo valore Celsius e stampa il risultato
// TODO: Prova a impostare il nuovo valore Fahrenheit e stampa il risultato
}
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
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker poolEsercitati da solo: Compilatore Go online