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.