Menu
Coddy logo textTech

Masquage de méthodes imbriquées

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy — leçon 39 sur 107.

Parfois, vous avez besoin que la structure externe fournisse sa propre implémentation d'une méthode que le type incorporé possède déjà. C'est ce qu'on appelle le shadowing, et cela vous permet de redéfinir les méthodes promues avec un comportement personnalisé.

Lorsque vous définissez une méthode sur la structure externe avec le même nom qu'une méthode intégrée, la méthode externe est prioritaire :

type Animal struct {
    Name string
}

func (a Animal) Speak() string {
    return "Some sound"
}

type Dog struct {
    Animal
    Breed string
}

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

Maintenant, lorsque vous appelez Speak() sur un Dog, la méthode externe est utilisée :

func main() {
    d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}
    
    fmt.Println(d.Speak())        // Woof! - méthode de Dog
    fmt.Println(d.Animal.Speak()) // Some sound - méthode de Animal
}

La méthode incorporée n'a pas disparu. Vous pouvez toujours y accéder explicitement via le nom du type incorporé. Ce modèle est utile lorsque vous souhaitez personnaliser le comportement tout en conservant l'implémentation originale disponible, peut-être pour l'appeler depuis votre méthode de substitution :

func (d Dog) Speak() string {
    return d.Animal.Speak() + " (but actually Woof!)"
}

Le masquage (shadowing) vous donne le contrôle sur le comportement exposé tout en conservant l'accès à l'original par une qualification explicite.

challenge icon

Défi

Facile

Construisons un système de notification où différents canaux de notification peuvent personnaliser la manière dont ils formatent et délivrent les messages. Vous utiliserez le masquage de méthode (method shadowing) pour permettre à des canaux spécifiques de surcharger le comportement par défaut tout en pouvant toujours accéder à l'implémentation originale si nécessaire.

Vous organiserez votre code sur trois fichiers :

  • base.go : Créez une structure BaseNotification avec les champs Title et Priority (tous deux des chaînes de caractères). Donnez-lui une méthode Format() string qui retourne la notification dans un format standard : [Priority] Title.
  • channels.go : Créez deux types de canaux de notification qui intègrent BaseNotification et masquent la méthode Format avec leurs propres implémentations :
    • EmailNotification avec un champ Recipient — sa méthode Format() doit retourner Email to [Recipient]: [Priority] Title
    • SlackNotification avec un champ Channel — sa méthode Format() doit appeler la méthode BaseNotification.Format() intégrée et ajouter #[Channel]: au début du résultat
  • main.go : Lisez les détails de la notification depuis l'entrée standard, créez les deux types de notifications, et démontrez le masquage en affichant :
    1. La sortie formatée de EmailNotification (en utilisant sa méthode masquée)
    2. Le format de base de EmailNotification (en appelant explicitement la méthode intégrée)
    3. La sortie formatée de SlackNotification (qui utilise la méthode de base en interne)

Les entrées suivantes seront fournies :

  • Ligne 1 : Titre de la notification
  • Ligne 2 : Niveau de priorité
  • Ligne 3 : Destinataire de l'e-mail
  • Ligne 4 : Nom du canal Slack

Par exemple, avec Server Alert, HIGH, admin@company.com, et ops-alerts, votre sortie devrait être :

Email to admin@company.com: HIGH Server Alert
[HIGH] Server Alert
#ops-alerts: [HIGH] Server Alert

Remarquez comment EmailNotification remplace complètement le formatage de base, tandis que SlackNotification l'améliore en appelant la méthode originale et en ajoutant le contexte du canal. Les deux approches démontrent différentes manières d'utiliser efficacement le masquage de méthode.

Aide-mémoire

Lorsque vous définissez une méthode sur une structure externe avec le même nom qu'une méthode d'un type incorporé, la méthode externe masque (surcharge) la méthode incorporée :

type Animal struct {
    Name string
}

func (a Animal) Speak() string {
    return "Some sound"
}

type Dog struct {
    Animal
    Breed string
}

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

Lors de l'appel de la méthode sur la structure externe, la méthode externe est prioritaire :

d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}

fmt.Println(d.Speak())        // Woof! - méthode de Dog
fmt.Println(d.Animal.Speak()) // Some sound - méthode de Animal

La méthode incorporée reste accessible via une qualification explicite en utilisant le nom du type incorporé. Vous pouvez appeler l'implémentation d'origine à l'intérieur de la méthode de surcharge :

func (d Dog) Speak() string {
    return d.Animal.Speak() + " (but actually Woof!)"
}

Essayez vous-même

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Lire le titre de la notification
	scanner.Scan()
	title := scanner.Text()
	
	// Lire le niveau de priorité
	scanner.Scan()
	priority := scanner.Text()
	
	// Lire le destinataire de l'e-mail
	scanner.Scan()
	recipient := scanner.Text()
	
	// Lire le nom du canal Slack
	scanner.Scan()
	channel := scanner.Text()
	
	// TODO: Créer une EmailNotification avec la notification de base, le titre, la priorité et le destinataire
	
	// TODO: Créer une SlackNotification avec la notification de base, le titre, la priorité et le canal
	
	// TODO: Afficher la sortie formatée de EmailNotification (en utilisant sa méthode masquée)
	
	// TODO: Afficher le format de base de EmailNotification (en appelant explicitement la méthode intégrée)
	
	// TODO: Afficher la sortie formatée de SlackNotification
	
	fmt.Println() // Espace réservé - à supprimer lors de l'implémentation
}
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