Elixir - Protokoły

Protokoły są mechanizmem umożliwiającym osiągnięcie polimorfizmu w Elixirze. Wysyłanie według protokołu jest dostępne dla dowolnego typu danych, o ile implementuje protokół.

Rozważmy przykład użycia protokołów. Użyliśmy funkcji o nazwieto_stringw poprzednich rozdziałach, aby przekonwertować z innych typów na typ łańcuchowy. To jest właściwie protokół. Działa zgodnie z danymi wejściowymi bez powodowania błędu. Może się to wydawać, że omawiamy funkcje dopasowywania wzorców, ale w miarę kontynuowania okazuje się, że jest inaczej.

Rozważ poniższy przykład, aby lepiej zrozumieć mechanizm protokołu.

Stwórzmy protokół, który wyświetli się, jeśli dane wejście jest puste, czy nie. Nazwiemy ten protokółblank?.

Definiowanie protokołu

Możemy zdefiniować protokół w Elixirze w następujący sposób -

defprotocol Blank do
   def blank?(data)
end

Jak widać, nie musimy definiować treści funkcji. Jeśli znasz interfejsy w innych językach programowania, możesz myśleć o protokole jako o zasadniczo tej samej rzeczy.

Tak więc ten protokół mówi, że wszystko, co go implementuje, musi mieć rozszerzenie empty?funkcji, chociaż to od implementatora zależy, jak funkcja odpowiada. Po zdefiniowaniu protokołu zrozummy, jak dodać kilka implementacji.

Wdrażanie protokołu

Ponieważ zdefiniowaliśmy protokół, musimy teraz powiedzieć mu, jak obsługiwać różne dane wejściowe, które może otrzymać. Skorzystajmy z wcześniejszego przykładu. Zaimplementujemy pusty protokół dla list, map i ciągów znaków. To pokaże, czy przekazana przez nas rzecz jest pusta, czy nie.

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

Możesz zaimplementować swój protokół dla tylu lub kilku typów, ile chcesz, niezależnie od tego, co ma sens dla użycia twojego protokołu. To był dość podstawowy przypadek użycia protokołów. Uruchomienie powyższego programu daje następujący wynik -

true
false
true
false

Note - Jeśli użyjesz tego dla innych typów niż te, dla których zdefiniowałeś protokół, spowoduje to błąd.