Menu
Coddy logo textTech

Implémentation implicite

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

Dans de nombreux langages orientés objet comme Java ou C#, vous devez déclarer explicitement qu’un type implémente une interface à l’aide de mots-clés comme implements. Go adopte une approche différente : l’implémentation des interfaces est implicite.

Un type satisfait une interface simplement en implémentant toutes ses méthodes. Il n’est nécessaire de déclarer cette relation nulle part. Le compilateur le déduit automatiquement.

type Writer interface {
    Write(data string) int
}

type FileWriter struct {
    Filename string
}

// FileWriter implémente implicitement Writer
func (f FileWriter) Write(data string) int {
    fmt.Println("Writing to", f.Filename)
    return len(data)
}

Remarquez qu’il n’y a pas de déclaration implements Writer sur FileWriter. Comme FileWriter possède une méthode Write(data string) int correspondant à la signature de l’interface, il satisfait automatiquement l’interface Writer.

Cette conception a une conséquence puissante : vous pouvez définir des interfaces après l’existence des types. Si une bibliothèque tierce possède un type avec les méthodes dont vous avez besoin, vous pouvez créer une interface à laquelle il satisfait déjà sans modifier le code d’origine.

func Save(w Writer, content string) {
    w.Write(content)
}

func main() {
    fw := FileWriter{Filename: "data.txt"}
    Save(fw, "Hello!")  // Fonctionne car FileWriter satisfait Writer
}

L’implémentation implicite permet de garder le code Go découplé et flexible. Les types n’ont pas besoin de connaître les interfaces à l’avance, ce qui facilite la composition de systèmes à partir de parties indépendantes.

challenge icon

Défi

Facile

Construisons un système de livraison de messages qui montre comment les types satisfont implicitement les interfaces en Go. Vous créerez différents types de messagers qui satisfont tous la même interface, sans jamais déclarer explicitement cette relation.

Vous organiserez votre code dans deux fichiers :

  • messengers.go : définissez une interface Messenger avec une seule méthode Send(message string) string. Créez ensuite deux structures qui satisferont implicitement cette interface :
    • EmailMessenger avec un champ Address (string)
    • SMSMessenger avec un champ PhoneNumber (string)
    Chaque structure doit avoir une méthode Send qui renvoie une chaîne décrivant la livraison. Aucune structure ne doit déclarer explicitement qu'elle implémente Messenger : Go le déterminera automatiquement en fonction des signatures des méthodes.
  • main.go : créez une fonction appelée DeliverMessage qui accepte n'importe quel Messenger ainsi qu'une chaîne de message, puis renvoie le résultat de l'appel à Send. Lisez les coordonnées saisies, créez les deux types de messagers et utilisez votre fonction pour envoyer des messages avec chacun d'eux.

Les entrées suivantes seront fournies :

  • Ligne 1 : adresse e-mail
  • Ligne 2 : numéro de téléphone
  • Ligne 3 : message à envoyer

Vos méthodes Send doivent renvoyer des chaînes dans les formats suivants :

  • EmailMessenger : Email to [Address]: [message]
  • SMSMessenger : SMS to [PhoneNumber]: [message]

Par exemple, avec alice@example.com, 555-1234 et Hello!, votre sortie devrait être :

Email to alice@example.com: Hello!
SMS to 555-1234: Hello!

L'idée essentielle est que votre fonction DeliverMessage accepte n'importe quel Messenger, et que EmailMessenger comme SMSMessenger satisfont cette interface simplement parce qu'ils possèdent une méthode Send correspondante. Il n'y a aucun mot-clé implements : l'implémentation implicite de Go s'en charge entièrement.

Essayez vous-même

package main

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

// TODO: Créer une fonction DeliverMessage qui accepte n'importe quel Messenger
// et une chaîne de message, puis renvoie le résultat de l'appel à Send

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Read email address
	email, _ := reader.ReadString('\n')
	email = email[:len(email)-1]
	
	// Lire le numéro de téléphone
	phone, _ := reader.ReadString('\n')
	phone = phone[:len(phone)-1]
	
	// Lire le message
	message, _ := reader.ReadString('\n')
	if len(message) > 0 && message[len(message)-1] == '\n' {
		message = message[:len(message)-1]
	}
	
	// TODO: Créer un EmailMessenger avec l'adresse e-mail
	
	// TODO: Créer un SMSMessenger avec le numéro de téléphone
	
	// TODO: Utiliser DeliverMessage pour envoyer le message via chaque messenger
	// et afficher les résultats
}
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