Modulelessen (1/5)
Interfaces: gedrag definiëren
Een interface in Go is een set methodehandtekeningen. Een waarde
implementeert de interface als deze al deze methoden heeft - nee
implements, geen extends, geen expliciete registratie. Het is de
model dat vaak "structureel typen" of "statisch duck-typen" wordt genoemd:
de compiler controleert de conformiteit tijdens het compileren, maar op basis van
vorm, niet op aangiften.
Een interface declareren
type Greeter interface {
Greet() string
}Conventie: namen die eindigen op -er voor interfaces met één methode
(Reader, Writer, Stringer, Closer). Kleine interfaces
(1–2 methoden) zijn idiomatisch: de standaardbibliotheek staat er vol mee
kleine interfaces die samen samenstellen (io.ReadWriter,
io.ReadCloser, …).
Impliciete implementatie
type Person struct{ Name string }
func (p Person) Greet() string {
return "ciao " + p.Name
}
// Person satisfies Greeter because it has the required method.
var s Greeter = Person{Name: "Ada"}
fmt.Println(s.Greet())Geen trefwoord. Als het type over de methoden beschikt, kan het worden toegewezen een variabele van dat interfacetype. Dat is het.
Polymorfisme via interface
type Robot struct{ ID string }
func (r Robot) Greet() string { return "bip " + r.ID }
func greet(s Greeter) {
fmt.Println(s.Greet())
}
greet(Person{Name: "Ada"})
greet(Robot{ID: "R2"})greet accepteert elk type dat voldoet aan Greeter. Dit is de Go-manier
van polymorfisme: geen hiërarchieën, alleen mogelijkheden.
De lege interface
var x interface{} = 42
var y any = "ciao" // any is the built-in alias of interface{}interface{} (of any sinds Go 1.18) vereist geen methoden, dus
waarde voldoet eraan. Handig voor generieke containers, maar om uit te pakken
de concrete waarde waarvoor u een typeverklaring of typeschakelaar nodig heeft
(volgende lessen).
Methodenset: waarde versus aanwijzerontvanger (preview)
Terugroepen uit module 5:
- Methoden met een waardeontvanger bevinden zich in de methodenset van zowel
Tals*T. - Methoden met een pointerontvanger bevinden zich ALLEEN in de methodenset van
*T.
Praktisch gevolg:
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }
type Incrementer interface { Inc() }
var i Incrementer = &Counter{} // OK: *Counter has Inc()
// var j Incrementer = Counter{} // ERROR: Counter (value) does NOTAls een methode een pointerontvanger heeft, moet u er een pointer aan toewijzen de interfacevariabele.
Probeer het
Definieer een interface Greeter met een enkele methode Greet() string.
Toon hint
Syntaxis: `type Naaminterface { Method(args) return }`.
Oplossing beschikbaar na 3 pogingen
Implementeer Greeter op een nieuw type robot met veld-ID-string; de methode retourneert 'bip' + ID.
Toon hint
Geen `implements`: definieer gewoon de methode met de juiste handtekening.
Oplossing beschikbaar na 3 pogingen
Hoe verklaar je dat type P de Greeter-interface implementeert?
type P struct{}
// ?Samenvatten
- Interface = set methodehandtekeningen; nee
implements. - Impliciete implementatie: zorg alleen voor de methoden met de juiste handtekening.
- Idiomatisch: kleine interfaces (1–2 methoden), namen in
-er. interface{}/any: accepteert elke waarde, verliest typeveiligheid.- Methode ingesteld: aanwijzerontvanger → alleen
*Tvoldoet aan de interface. - Ga voor polymorfisme: interface-getypeerde parameters, geen hiërarchieën.