Elisir - Protocolli

I protocolli sono un meccanismo per ottenere il polimorfismo in Elixir. Il dispacciamento su un protocollo è disponibile per qualsiasi tipo di dati fintanto che implementa il protocollo.

Consideriamo un esempio di utilizzo dei protocolli. Abbiamo usato una funzione chiamatato_stringnei capitoli precedenti per convertire da altri tipi al tipo stringa. Questo è in realtà un protocollo. Agisce in base all'input fornito senza produrre errori. Potrebbe sembrare che stiamo discutendo di funzioni di pattern matching, ma man mano che procediamo oltre, risulta diverso.

Considera il seguente esempio per comprendere meglio il meccanismo del protocollo.

Creiamo un protocollo che verrà visualizzato se l'input fornito è vuoto o meno. Chiameremo questo protocolloblank?.

Definizione di un protocollo

Possiamo definire un protocollo in Elixir nel modo seguente:

defprotocol Blank do
   def blank?(data)
end

Come puoi vedere, non è necessario definire un corpo per la funzione. Se hai familiarità con le interfacce in altri linguaggi di programmazione, puoi pensare a un protocollo essenzialmente come la stessa cosa.

Quindi questo protocollo dice che tutto ciò che lo implementa deve avere un'estensione empty?funzione, sebbene spetti all'implementatore come la funzione risponde. Con il protocollo definito, vediamo di capire come aggiungere un paio di implementazioni.

Attuazione di un protocollo

Poiché abbiamo definito un protocollo, ora dobbiamo dirgli come gestire i diversi input che potrebbe ottenere. Partiamo dall'esempio che avevamo preso in precedenza. Implementeremo il protocollo vuoto per elenchi, mappe e stringhe. Questo mostrerà se la cosa che abbiamo passato è vuota o no.

#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")

Puoi implementare il tuo protocollo per tutti i tipi che desideri, qualunque cosa abbia senso per l'utilizzo del tuo protocollo. Questo è stato un caso d'uso piuttosto semplice dei protocolli. Quando il programma di cui sopra viene eseguito, produce il seguente risultato:

true
false
true
false

Note - Se lo usi per qualsiasi tipo diverso da quelli per cui hai definito il protocollo, produrrà un errore.