Поведения в Elixir (и Erlang) — это способ отделить и абстрагировать общую часть компонента (которая становится модулем поведения) от конкретной части (которая становится модулем обратного вызова). Поведение обеспечивает способ —
- Определите набор функций, которые должны быть реализованы модулем.
- Убедитесь, что модуль реализует все функции в этом наборе.
Если вам нужно, вы можете подумать о поведении, подобном интерфейсам в объектно-ориентированных языках, таких как Java: набор сигнатур функций, которые должен реализовывать модуль.
Определение поведения
Давайте рассмотрим пример для создания нашего собственного поведения, а затем используем это общее поведение для создания модуля. Мы определим поведение, которое приветствует людей на разных языках.
defmodule GreetBehaviour do @callback say_hello(name :: string) :: nil @callback say_bye(name :: string) :: nil end
Директива @callback используется для перечисления функций, которые нужно будет определить принимающим модулям. Также указывается нет. аргументов, их тип и их возвращаемые значения.
Принятие Поведения
Мы успешно определили поведение. Теперь мы примем и внедрим его в несколько модулей. Давайте создадим два модуля, реализующих это поведение на английском и испанском языках.
defmodule GreetBehaviour do @callback say_hello(name :: string) :: nil @callback say_bye(name :: string) :: nil end defmodule EnglishGreet do @behaviour GreetBehaviour def say_hello(name), do: IO.puts("Hello " <> name) def say_bye(name), do: IO.puts("Goodbye, " <> name) end defmodule SpanishGreet do @behaviour GreetBehaviour def say_hello(name), do: IO.puts("Hola " <> name) def say_bye(name), do: IO.puts("Adios " <> name) end EnglishGreet.say_hello("Ayush") EnglishGreet.say_bye("Ayush") SpanishGreet.say_hello("Ayush") SpanishGreet.say_bye("Ayush")
Когда вышеуказанная программа запущена, она дает следующий результат —
Hello Ayush Goodbye, Ayush Hola Ayush Adios Ayush
Как вы уже видели, мы применяем поведение, используя директиву @behaviour в модуле. Мы должны определить все функции, реализованные в поведении для всех дочерних модулей. Это можно грубо считать эквивалентным интерфейсам на языках ООП.