Учебники

Эликсир — Протоколы

Протоколы являются механизмом достижения полиморфизма в эликсире. Диспетчеризация по протоколу доступна для любого типа данных, если он реализует протокол.

Давайте рассмотрим пример использования протоколов. Мы использовали функцию to_string в предыдущих главах для преобразования других типов в строковый тип. Это на самом деле протокол. Он действует в соответствии с вводимыми данными без ошибок. Может показаться, что мы обсуждаем функции сопоставления с образцом, но если мы продолжим работу, то получится иначе.

Рассмотрим следующий пример, чтобы лучше понять механизм протокола.

Давайте создадим протокол, который будет отображать, является ли данный ввод пустым или нет. Мы будем называть этот протокол пустым? ,

Определение протокола

Мы можем определить протокол в Elixir следующим образом —

defprotocol Blank do
   def blank?(data)
end

Как видите, нам не нужно определять тело для функции. Если вы знакомы с интерфейсами в других языках программирования, вы можете думать о протоколе как о том же самом.

Таким образом, этот протокол говорит, что все, что реализует его, должно быть пустым? функции, хотя это зависит от разработчика относительно того, как функция отвечает. Определив протокол, давайте разберемся, как добавить пару реализаций.

Реализация протокола

Поскольку мы определили протокол, теперь нам нужно указать ему, как обрабатывать различные входные данные, которые он может получить. Давайте продолжим на примере, который мы взяли ранее. Мы реализуем пустой протокол для списков, карт и строк. Это покажет, пусто или нет то, что мы передали.

Live Demo

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

Вы можете реализовать свой протокол для любого количества или нескольких типов, в зависимости от того, что имеет смысл для использования вашего протокола. Это был довольно простой случай использования протоколов. Когда вышеуказанная программа запущена, она дает следующий результат —

true
false
true
false

Примечание. Если вы используете это для любых типов, отличных от тех, для которых вы определили протокол, это приведет к ошибке.