Menu
Coddy logo textTech

Polymorphisme via les interfaces

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 41 sur 107.

Le polymorphisme permet de traiter uniformément différents types grâce à une interface commune. En Go, cela est réalisé entièrement au moyen d’interfaces, sans héritage ni hiérarchies de classes.

Lorsqu’une fonction accepte un type d’interface comme paramètre, tout type concret qui implémente cette interface peut être transmis. La fonction n’a pas besoin de connaître le type spécifique. Elle se soucie uniquement du comportement défini par l’interface :

type Speaker interface {
    Speak() string
}

type Dog struct{ Name string }
func (d Dog) Speak() string { return "Woof!" }

type Cat struct{ Name string }
func (c Cat) Speak() string { return "Meow!" }

func MakeSound(s Speaker) {
    fmt.Println(s.Speak())
}

Maintenant, MakeSound fonctionne avec tout type qui possède une méthode Speak() :

func main() {
    dog := Dog{Name: "Rex"}
    cat := Cat{Name: "Whiskers"}
    
    MakeSound(dog)  // Ouaf !
    MakeSound(cat)  // Miaou !
}

Le même appel de fonction produit un comportement différent selon le type réel transmis. C’est le polymorphisme en action. La fonction MakeSound est écrite une seule fois, mais fonctionne avec un nombre illimité de types, tant qu’ils satisfont à l’interface Speaker.

Cette approche rend votre code flexible et extensible. Ajouter un nouveau type qui parle ne nécessite aucune modification des fonctions existantes : il suffit d’implémenter l’interface, et cela fonctionne automatiquement.

challenge icon

Défi

Facile

Construisons un système de description de véhicules qui illustre le polymorphisme en action. Vous créerez différents types de véhicules qui partagent tous un comportement commun grâce à une interface, puis vous écrirez une seule fonction qui fonctionne avec n’importe quel véhicule.

Vous organiserez votre code sur deux fichiers :

  • vehicles.go : définissez une interface Describer qui exige une méthode Describe() string. Créez ensuite trois types de véhicules qui implémentent chacun cette interface à leur manière :
    • Car avec les champs Brand et Model. Son Describe() renvoie Car: [Brand] [Model]
    • Motorcycle avec les champs Brand et EngineCC (int). Son Describe() renvoie Motorcycle: [Brand] [EngineCC]cc
    • Bicycle avec le champ Type (comme "Mountain" ou "Road"). Son Describe() renvoie Bicycle: [Type]
  • main.go : créez une fonction appelée PrintDescription qui accepte n’importe quel Describer et affiche le résultat de l’appel à Describe(). Lisez les détails des véhicules depuis l’entrée, créez un véhicule de chaque type, puis transmettez chacun à PrintDescription afin de montrer que la même fonction fonctionne avec les trois types différents.

Les entrées suivantes seront fournies :

  • Ligne 1 : marque de la voiture
  • Ligne 2 : modèle de la voiture
  • Ligne 3 : marque de la moto
  • Ligne 4 : cylindrée de la moto en CC (entier)
  • Ligne 5 : type de vélo

Par exemple, avec Toyota, Camry, Honda, 600 et Mountain, votre sortie devrait être :

Car: Toyota Camry
Motorcycle: Honda 600cc
Bicycle: Mountain

Remarquez que PrintDescription n’a pas besoin de savoir si elle reçoit une voiture, une moto ou un vélo. Elle appelle simplement Describe(), et chaque type répond avec sa propre sortie unique. C’est cela, le polymorphisme : une fonction, plusieurs comportements.

Essayez vous-même

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// TODO: Créer une fonction appelée PrintDescription qui accepte n'importe quel Describer
// et imprime le résultat de l'appel à Describe()

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Lire les détails de la voiture
	carBrand, _ := reader.ReadString('\n')
	carBrand = strings.TrimSpace(carBrand)
	carModel, _ := reader.ReadString('\n')
	carModel = strings.TrimSpace(carModel)

	// Lire les détails de la moto
	motoBrand, _ := reader.ReadString('\n')
	motoBrand = strings.TrimSpace(motoBrand)
	motoEngineStr, _ := reader.ReadString('\n')
	motoEngineStr = strings.TrimSpace(motoEngineStr)
	motoEngine, _ := strconv.Atoi(motoEngineStr)

	// Lire les détails du vélo
	bicycleType, _ := reader.ReadString('\n')
	bicycleType = strings.TrimSpace(bicycleType)

	// TODO: Créer une Car, une Motorcycle et un Bicycle en utilisant les valeurs d'entrée

	// TODO: Appeler PrintDescription pour chaque véhicule afin de démontrer le polymorphisme
	fmt.Println("TODO: Print vehicle descriptions")
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Go en ligne