Direct naar de hoofdinhoud
Module 6 · Les 1 van 526/50 in de cursus~12 min
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

Go
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

Go
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

Go
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

Go
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 T als *T.
  • Methoden met een pointerontvanger bevinden zich ALLEEN in de methodenset van *T.

Praktisch gevolg:

Go
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 NOT

Als een methode een pointerontvanger heeft, moet u er een pointer aan toewijzen de interfacevariabele.

Probeer het

Oefening#go.m6.l1.e1
Pogingen: 0Laden…

Definieer een interface Greeter met een enkele methode Greet() string.

Editor laden…
Toon hint

Syntaxis: `type Naaminterface { Method(args) return }`.

Oplossing beschikbaar na 3 pogingen

Oefening#go.m6.l1.e2
Pogingen: 0Laden…

Implementeer Greeter op een nieuw type robot met veld-ID-string; de methode retourneert 'bip' + ID.

Editor laden…
Toon hint

Geen `implements`: definieer gewoon de methode met de juiste handtekening.

Oplossing beschikbaar na 3 pogingen

Quiz#go.m6.l1.e3
Klaar

Hoe verklaar je dat type P de Greeter-interface implementeert?

Go
type P struct{}
// ?
Antwoordmogelijkheden

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 *T voldoet aan de interface.
  • Ga voor polymorfisme: interface-getypeerde parameters, geen hiërarchieën.