Les interfícies són una característica poderosa i flexible en Go que permeten definir comportaments que poden ser implementats per diferents tipus. En aquest tema, explorarem què són les interfícies, com es defineixen i com es poden utilitzar per escriure codi més flexible i reutilitzable.

Què és una Interfície?

Una interfície en Go és un tipus que especifica un conjunt de mètodes. Qualsevol tipus que implementi aquests mètodes es considera que implementa la interfície. Això permet que diferents tipus puguin ser tractats de manera uniforme si implementen la mateixa interfície.

Definició d'una Interfície

Una interfície es defineix utilitzant la paraula clau interface. Aquí teniu un exemple d'una interfície simple:

type Describer interface {
    Describe() string
}

En aquest exemple, la interfície Describer defineix un únic mètode Describe que retorna una cadena de text (string).

Implementació d'una Interfície

Qualsevol tipus que implementi el mètode Describe es considera que implementa la interfície Describer. No cal que el tipus declari explícitament que implementa la interfície; simplement ha de tenir els mètodes requerits.

type Person struct {
    Name string
    Age  int
}

func (p Person) Describe() string {
    return fmt.Sprintf("%s is %d years old.", p.Name, p.Age)
}

En aquest exemple, el tipus Person implementa la interfície Describer perquè té un mètode Describe que retorna una cadena de text.

Ús d'Interfícies

Les interfícies es poden utilitzar per escriure funcions que treballen amb qualsevol tipus que implementi la interfície. Això permet escriure codi més general i reutilitzable.

func PrintDescription(d Describer) {
    fmt.Println(d.Describe())
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    PrintDescription(p)
}

En aquest exemple, la funció PrintDescription pot treballar amb qualsevol tipus que implementi la interfície Describer.

Interfícies Integrades

Go proporciona diverses interfícies integrades que són àmpliament utilitzades. Algunes de les més comunes són:

  • io.Reader: Defineix el mètode Read(p []byte) (n int, err error).
  • io.Writer: Defineix el mètode Write(p []byte) (n int, err error).

Aquestes interfícies són utilitzades per a operacions d'entrada i sortida.

Interfícies Embegudes

Les interfícies poden incloure altres interfícies, permetent la creació de jerarquies d'interfícies.

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

type ReadWriter interface {
    Reader
    Writer
}

En aquest exemple, la interfície ReadWriter inclou les interfícies Reader i Writer, de manera que qualsevol tipus que implementi ReadWriter ha de tenir els mètodes Read i Write.

Exercicis Pràctics

Exercici 1: Implementar una Interfície

Defineix una interfície Shape amb un mètode Area que retorna un float64. Implementa aquesta interfície per als tipus Circle i Rectangle.

package main

import (
    "fmt"
    "math"
)

type Shape interface {
    Area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func main() {
    c := Circle{Radius: 5}
    r := Rectangle{Width: 3, Height: 4}

    shapes := []Shape{c, r}
    for _, shape := range shapes {
        fmt.Printf("Area: %.2f\n", shape.Area())
    }
}

Exercici 2: Interfícies i Funcions

Escriu una funció TotalArea que accepti una llista de Shape i retorni la suma de les seves àrees.

func TotalArea(shapes []Shape) float64 {
    var total float64
    for _, shape := range shapes {
        total += shape.Area()
    }
    return total
}

func main() {
    c := Circle{Radius: 5}
    r := Rectangle{Width: 3, Height: 4}

    shapes := []Shape{c, r}
    fmt.Printf("Total Area: %.2f\n", TotalArea(shapes))
}

Errors Comuns

  • No Implementar Tots els Mètodes: Assegura't que el tipus implementa tots els mètodes de la interfície.
  • Confusió amb Tipus: Recorda que qualsevol tipus que implementi els mètodes d'una interfície es considera que implementa la interfície, sense necessitat de declaracions explícites.

Resum

Les interfícies en Go permeten definir comportaments que poden ser implementats per diferents tipus, proporcionant una manera flexible i poderosa d'escriure codi reutilitzable. Hem vist com definir i implementar interfícies, així com alguns exemples pràctics i exercicis per reforçar els conceptes apresos. En el proper tema, explorarem la reflexió en Go, una altra característica avançada que permet inspeccionar i manipular tipus en temps d'execució.

© Copyright 2024. Tots els drets reservats