Menu
Coddy logo textTech

Duck typing en Go

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

Le terme duck typing vient de l’expression : « Si ça marche comme un canard et fait coin-coin comme un canard, alors c’est un canard. » En Go, cela signifie qu’un type n’a pas besoin de déclarer explicitement qu’il implémente une interface. Il lui suffit de disposer des bonnes méthodes.

Considérez cette interface et deux types totalement indépendants :

type Quacker interface {
    Quack() string
}

type Duck struct{}
func (d Duck) Quack() string { return "Quack!" }

type Robot struct{}
func (r Robot) Quack() string { return "Beep-quack!" }

Ni Duck ni Robot ne mentionnent Quacker nulle part dans leurs définitions. Pourtant, tous deux respectent l’interface simplement parce qu’ils possèdent une méthode Quack() avec la signature correcte :

func MakeItQuack(q Quacker) {
    fmt.Println(q.Quack())
}

func main() {
    MakeItQuack(Duck{})   // Coin-coin !
    MakeItQuack(Robot{})  // Bip-coin !
}

Cette satisfaction implicite est puissante, car elle vous permet de définir des interfaces après l’existence des types. Vous pouvez créer une interface correspondant à des types provenant de packages externes sans modifier leur code source. Les types n’ont pas besoin de connaître votre interface. Ils doivent simplement se comporter correctement.

Le typage canard en Go vous offre la flexibilité des langages dynamiques tout en maintenant la sécurité des types à la compilation. Le compilateur vérifie que les types possèdent effectivement les méthodes requises avant d’autoriser leur utilisation comme valeurs d’interface.

challenge icon

Défi

Facile

Construisons un système de messagerie qui démontre le duck typing en action. Tu vas créer des types complètement indépendants qui peuvent tous envoyer des messages via une interface commune, sans qu’aucun d’entre eux ne déclare explicitement l’implémenter.

Tu organiseras ton code sur trois fichiers :

  • messengers.go : crée trois structures indépendantes qui ont par hasard le même comportement :
    • Phone avec un champ Number. Sa méthode SendMessage(text string) string renvoie SMS to [Number]: [text]
    • Computer avec un champ Email. Sa méthode SendMessage(text string) string renvoie Email to [Email]: [text]
    • Pigeon avec un champ Name. Sa méthode SendMessage(text string) string renvoie [Name] carries: [text]
    Remarque qu’aucun de ces types ne mentionne d’interface. Ils ont simplement, par hasard, la même signature de méthode.
  • sender.go : définis une interface Messenger qui requiert une méthode SendMessage(text string) string. Crée une fonction appelée Broadcast qui prend une tranche de Messenger et une chaîne de caractères représentant un message, puis renvoie une tranche de chaînes contenant le résultat de l’appel de SendMessage sur chaque messager.
  • main.go : lis les informations saisies, crée un exemplaire de chaque type de messager, rassemble-les dans une tranche de Messenger et utilise Broadcast pour envoyer un message à chacun d’eux. Affiche chaque résultat sur sa propre ligne.

Les entrées suivantes seront fournies :

  • Ligne 1 : numéro de téléphone
  • Ligne 2 : adresse e-mail
  • Ligne 3 : nom du pigeon
  • Ligne 4 : message à diffuser

Par exemple, avec 555-1234, alice@mail.com, Winston et Hello World, ta sortie devrait être :

SMS to 555-1234: Hello World
Email to alice@mail.com: Hello World
Winston carries: Hello World

L’idée essentielle est que Phone, Computer et Pigeon n’ont rien en commun. Ils ne partagent pas de type de base et n’implémentent pas explicitement Messenger. Pourtant, comme ils « >couinent » tous de la même manière (ils possèdent la méthode correspondante), Go permet de tous les utiliser comme valeurs Messenger. C’est le duck typing en action.

Essayez vous-même

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Lire le numéro de téléphone
	scanner.Scan()
	phoneNumber := scanner.Text()
	
	// Read email address
	scanner.Scan()
	email := scanner.Text()
	
	// Lire le nom du pigeon
	scanner.Scan()
	pigeonName := scanner.Text()
	
	// Lire le message à diffuser
	scanner.Scan()
	message := scanner.Text()
	
	// TODO: Créer un de chaque type de messager (Phone, Computer, Pigeon)
	
	// TODO: Collecter tous les messagers dans une slice de Messenger
	
	// TODO: Utiliser Broadcast pour envoyer le message via tous les messagers
	
	// TODO: Afficher chaque résultat sur sa propre ligne
	
	// Placeholder pour utiliser les variables (à supprimer lors de l'implémentation)
	_ = phoneNumber
	_ = email
	_ = pigeonName
	_ = message
}
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