Протоколы являются механизмом достижения полиморфизма в эликсире. Диспетчеризация по протоколу доступна для любого типа данных, если он реализует протокол.
Давайте рассмотрим пример использования протоколов. Мы использовали функцию to_string в предыдущих главах для преобразования других типов в строковый тип. Это на самом деле протокол. Он действует в соответствии с вводимыми данными без ошибок. Может показаться, что мы обсуждаем функции сопоставления с образцом, но если мы продолжим работу, то получится иначе.
Рассмотрим следующий пример, чтобы лучше понять механизм протокола.
Давайте создадим протокол, который будет отображать, является ли данный ввод пустым или нет. Мы будем называть этот протокол пустым? ,
Определение протокола
Мы можем определить протокол в Elixir следующим образом —
defprotocol Blank do def blank?(data) end
Как видите, нам не нужно определять тело для функции. Если вы знакомы с интерфейсами в других языках программирования, вы можете думать о протоколе как о том же самом.
Таким образом, этот протокол говорит, что все, что реализует его, должно быть пустым? функции, хотя это зависит от разработчика относительно того, как функция отвечает. Определив протокол, давайте разберемся, как добавить пару реализаций.
Реализация протокола
Поскольку мы определили протокол, теперь нам нужно указать ему, как обрабатывать различные входные данные, которые он может получить. Давайте продолжим на примере, который мы взяли ранее. Мы реализуем пустой протокол для списков, карт и строк. Это покажет, пусто или нет то, что мы передали.
#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
Примечание. Если вы используете это для любых типов, отличных от тех, для которых вы определили протокол, это приведет к ошибке.