Elixir - Protocoles

Les protocoles sont un mécanisme pour réaliser le polymorphisme dans Elixir. La distribution sur un protocole est disponible pour tout type de données tant qu'il implémente le protocole.

Prenons un exemple d'utilisation de protocoles. Nous avons utilisé une fonction appeléeto_stringdans les chapitres précédents pour convertir d'autres types en type chaîne. C'est en fait un protocole. Il agit en fonction de l'entrée qui est donnée sans produire d'erreur. Cela peut sembler être en train de discuter des fonctions de correspondance de modèles, mais au fur et à mesure que nous progressons, cela s'avère différent.

Prenons l'exemple suivant pour mieux comprendre le mécanisme du protocole.

Créons un protocole qui affichera si l'entrée donnée est vide ou non. Nous appellerons ce protocoleblank?.

Définition d'un protocole

Nous pouvons définir un protocole dans Elixir de la manière suivante -

defprotocol Blank do
   def blank?(data)
end

Comme vous pouvez le voir, nous n'avons pas besoin de définir un corps pour la fonction. Si vous êtes familier avec les interfaces dans d'autres langages de programmation, vous pouvez considérer un protocole comme essentiellement la même chose.

Donc, ce protocole dit que tout ce qui le met en œuvre doit avoir un empty?fonction, bien que ce soit à l'implémenteur de savoir comment la fonction répond. Avec le protocole défini, comprenons comment ajouter quelques implémentations.

Mettre en œuvre un protocole

Depuis que nous avons défini un protocole, nous devons maintenant lui dire comment gérer les différentes entrées qu'il pourrait obtenir. Penchons-nous sur l'exemple que nous avions pris précédemment. Nous implémenterons le protocole vierge pour les listes, les cartes et les chaînes. Cela montrera si la chose que nous avons passée est vide ou non.

#Defining the protocol
defprotocol Blank do
   def blank?(data)
end

#Implementing the protocol for lists
defimpl Blank, for: List do
   def blank?([]), do: true
   def blank?(_), do: false
end

#Implementing the protocol for strings
defimpl Blank, for: BitString do
   def blank?(""), do: true
   def blank?(_), do: false
end

#Implementing the protocol for maps
defimpl Blank, for: Map do
   def blank?(map), do: map_size(map) == 0
end

IO.puts(Blank.blank? [])
IO.puts(Blank.blank? [:true, "Hello"])
IO.puts(Blank.blank? "")
IO.puts(Blank.blank? "Hi")

Vous pouvez implémenter votre protocole pour autant ou aussi peu de types que vous le souhaitez, tout ce qui a du sens pour l'utilisation de votre protocole. C'était un cas d'utilisation assez basique des protocoles. Lorsque le programme ci-dessus est exécuté, il produit le résultat suivant -

true
false
true
false

Note - Si vous utilisez ceci pour des types autres que ceux pour lesquels vous avez défini le protocole, cela produira une erreur.