I protocolli sono un meccanismo per ottenere il polimorfismo in Elixir quando vuoi che il comportamento vari in base al tipo di dato.
I protocolli si definiscono con defprotocol e contengono una o più intestazioni di funzione.
defprotocol Reversible do
def reverse(term)
end
I protocolli si possono implementare con defimpl.
defimpl Reversible, for: List do
def reverse(term) do
Enum.reverse(term)
end
end
Un protocollo può essere implementato per qualsiasi tipo di dato esistente in Elixir o per uno struct.
Quando si chiama una funzione di un protocollo, l'implementazione appropriata viene scelta automaticamente in base al tipo del primo argomento.
Stai sviluppando il tuo videogioco di ruolo. Nel tuo gioco ci sono personaggi e oggetti. Una delle tante azioni che puoi fare con un oggetto è far mangiare l'oggetto a un personaggio.
Non tutti gli oggetti sono commestibili, e non tutti gli oggetti commestibili hanno gli stessi effetti sul personaggio. Alcuni oggetti, quando vengono mangiati, si trasformano in un oggetto diverso (ad esempio, se mangi una mela, ti rimane il torsolo).
Per permettere tutta questa flessibilità, hai deciso di creare un protocollo Edible che alcuni oggetti possono implementare.
Crea il protocollo RPG.Edible. Il protocollo ha una sola funzione: eat. La funzione eat accetta un oggetto e un personaggio e restituisce un sottoprodotto e un personaggio.
Implementa il protocollo RPG.Edible per l'oggetto RPG.LoafOfBread. Quando viene mangiata, una pagnotta di pane dà al personaggio 5 punti vita e non ha sottoprodotti.
RPG.Edible.eat(%RPG.LoafOfBread{}, %RPG.Character{health: 31})
# => {nil, %RPG.Character{health: 36, mana: 0}}
Implementa il protocollo RPG.Edible per l'oggetto RPG.ManaPotion. Quando viene mangiata, una pozione di mana dà al personaggio tanti punti mana quanta è la forza della pozione, e produce una bottiglia vuota.
RPG.Edible.eat(%RPG.ManaPotion{strength: 13}, %RPG.Character{mana: 50})
# => {%RPG.EmptyBottle{}, %RPG.Character{health: 100, mana: 63}}
Implementa il protocollo RPG.Edible per l'oggetto RPG.Poison. Quando viene mangiato, un veleno toglie tutti i punti vita al personaggio e produce una bottiglia vuota.
RPG.Edible.eat(%RPG.Poison{}, %RPG.Character{health: 3000})
# => {%RPG.EmptyBottle{}, %RPG.Character{health: 0, mana: 0}}
Iscriviti a Exercism per imparare e padroneggiare Elixir con 58 concetti168 esercizi e il mentoring di persone reali, tutto gratis.