Ricevitore e Interfaccia
I metodi con ricevitori di valore possono essere chiamati utilizzando sia i valori che i puntatori.
I metodi con ricevitori di puntatore possono essere chiamati solo utilizzando puntatori o valori indirizzabili.
Per esempio,
type S struct {
data string
}
func (s S) Leggi() string {
return s.data
}
func (s *S) Scrivi(str string) {
s.data = str
}
sVals := map[int]S{1: {"A"}}
// Puoi chiamare Leggi solo utilizzando un valore
sVals[1].Leggi()
// Questo non compilerà:
// sVals[1].Scrivi("test")
sPtrs := map[int]*S{1: {"A"}}
// Sia i metodi Leggi che Scrivi possono essere chiamati utilizzando un puntatore
sPtrs[1].Leggi()
sPtrs[1].Scrivi("test")
Allo stesso modo, anche se un metodo ha un ricevitore di valore, può soddisfare un'interfaccia utilizzando un ricevitore di puntatore.
type F interface {
f()
}
type S1 struct{}
func (s S1) f() {}
type S2 struct{}
func (s *S2) f() {}
s1Val := S1{}
s1Ptr := &S1{}
s2Val := S2{}
s2Ptr := &S2{}
var i F
i = s1Val
i = s1Ptr
i = s2Ptr
// Il seguente codice non compilerà perché s2Val è un valore e il metodo f di S2 non ha un ricevitore di valore
// i = s2Val
Effective Go contiene ottime spiegazioni su puntatori vs. valori.
Note aggiuntive:
- Un tipo può avere un insieme di metodi con ricevitori di valore e un insieme di metodi con ricevitori di puntatore
- L'insieme di metodi con ricevitori di valore è un sottoinsieme dell'insieme di metodi con ricevitori di puntatore, ma non viceversa
- Regole
- Gli oggetti valore possono utilizzare solo l'insieme di metodi con ricevitori di valore
- Gli oggetti puntatore possono utilizzare l'insieme di metodi con ricevitori di valore + l'insieme di metodi con ricevitori di puntatore
- Corrispondenza dell'interfaccia (o implementazione)
- Il tipo corrisponde all'interfaccia se implementa tutti i metodi dell'interfaccia
- In particolare, è necessario o che l'insieme di metodi valore del tipo corrisponda all'interfaccia o che l'insieme di metodi puntatore corrisponda all'interfaccia
Esistono due tipi specifici di corrispondenza:
- L'insieme di metodi valore che corrisponde all'interfaccia
- Va bene assegnare un oggetto valore o puntatore a una variabile di interfaccia poiché entrambi contengono l'insieme di metodi valore
- L'insieme di metodi puntatore che corrisponde all'interfaccia
- Solo un oggetto puntatore può essere assegnato a una variabile di interfaccia poiché solo l'insieme di metodi puntatore corrisponde all'interfaccia
- Se viene assegnato un oggetto valore a una variabile di interfaccia, attiverà un meccanismo di controllo della vitalità dell'interfaccia durante la compilazione
Perché i = s2Val genera un errore, è perché l'insieme di metodi valore e l'interfaccia non corrispondono.