Promozione dei metodi
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 36 di 107.
Proprio come l'incorporamento di struct promuove i campi nella struct esterna, Go promuove anche i metodi dei tipi incorporati. Questo significa che puoi chiamare i metodi definiti sulla struct incorporata direttamente sulla struct esterna.
type Engine struct {
Horsepower int
}
func (e Engine) Start() string {
return "Engine started"
}
type Car struct {
Model string
Engine // incorporato
}
Poiché Car incorpora Engine, il metodo Start() viene promosso automaticamente:
func main() {
c := Car{
Model: "Sedan",
Engine: Engine{Horsepower: 200},
}
fmt.Println(c.Start()) // Motor arrancado
fmt.Println(c.Engine.Start()) // también funciona
}
Questa promozione ha una conseguenza importante per le interfacce. Se il tipo incorporato soddisfa un'interfaccia, anche il tipo esterno la soddisfa automaticamente:
type Starter interface {
Start() string
}
func Ignite(s Starter) {
fmt.Println(s.Start())
}
func main() {
c := Car{Model: "Sedan", Engine: Engine{Horsepower: 200}}
Ignite(c) // Car soddisfa Starter tramite Engine
}
Il tipo Car non implementa mai esplicitamente Starter, eppure soddisfa l’interfaccia perché il suo Engine incorporato ha il metodo richiesto. È così che Go consente di riutilizzare il comportamento senza ricorrere all’ereditarietà tradizionale.
Sfida
FacileCostruiamo un sistema di riproduzione musicale che dimostri come i metodi dei tipi incorporati vengono promossi al tipo esterno e come ciò consenta di soddisfare un’interfaccia tramite composizione.
Organizzerai il codice in due file:
audio.go: crea gli elementi costitutivi del tuo riproduttore musicale:- Una struttura
AudioPlayercon un campoBrand(stringa) e un metodoPlay() stringche restituisce[Brand] playing audio - Un’interfaccia
Playableche richiede un metodoPlay() string - Una struttura
Smartphonecon un campoModelche incorporaAudioPlayer - Una struttura
Tabletcon un campoModelche incorporaAudioPlayer
- Una struttura
main.go: crea una funzione chiamataStartPlaybackche accetta qualsiasiPlayablee restituisce il risultato della chiamata aPlay(). Leggi le informazioni sui dispositivi dall’input, crea uno Smartphone e un Tablet e dimostra che entrambi soddisfano l’interfacciaPlayabletramite il loroAudioPlayerincorporato, anche se nessuno dei due tipi implementa esplicitamentePlay().
Verranno forniti i seguenti input:
- Riga 1: nome del modello dello Smartphone
- Riga 2: marca audio dello Smartphone
- Riga 3: nome del modello del Tablet
- Riga 4: marca audio del Tablet
Per ciascun dispositivo, stampa il suo modello seguito dal risultato del passaggio a StartPlayback.
Ad esempio, dati iPhone 15, Apple Audio, iPad Pro e Beats, l’output dovrebbe essere:
iPhone 15
Apple Audio playing audio
iPad Pro
Beats playing audioNota come sia Smartphone sia Tablet possano essere passati a StartPlayback perché il metodo Play() di AudioPlayer viene promosso automaticamente a ciascun tipo esterno, soddisfacendo l’interfaccia Playable senza bisogno di codice aggiuntivo.
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
)
// TODO: Crea una funzione StartPlayback che accetti qualsiasi Playable
// e restituisca il risultato della chiamata a Play()
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Leggi il modello dello smartphone
scanner.Scan()
smartphoneModel := scanner.Text()
// Leggi la marca del sistema audio dello smartphone
scanner.Scan()
smartphoneBrand := scanner.Text()
// Leggi il modello del tablet
scanner.Scan()
tabletModel := scanner.Text()
// Leggi la marca del sistema audio del tablet
scanner.Scan()
tabletBrand := scanner.Text()
// TODO: Crea uno Smartphone con AudioPlayer incorporato
// TODO: Crea un Tablet con AudioPlayer incorporato
// TODO: Stampa il modello dello smartphone, poi chiama StartPlayback con lo smartphone
// TODO: Stampa il modello del tablet, poi chiama StartPlayback con il tablet
_ = smartphoneModel
_ = smartphoneBrand
_ = tabletModel
_ = tabletBrand
fmt.Println("TODO: Complete the implementation")
}
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