Треки
/
Elixir
Elixir
/
Салабус
/
Поведінки
По

Поведінки у Elixir

1 вправа

Про концепцію Поведінки

Поведінки дають змогу визначати інтерфейси (набори функцій і макросів) у модулі поведінки, які згодом можуть бути реалізовані різними модулями-колбеками. Завдяки спільному інтерфейсу ці модулі-колбеки можна використовувати взаємозамінно.

Note

Звернімо увагу на британське написання «behaviours».

Визначення поведінок

Щоб визначити поведінку, потрібно створити новий модуль і вказати список функцій, які входять до бажаного інтерфейсу. Кожну функцію потрібно визначити за допомогою атрибута модуля @callback. Синтаксис такий самий, як у специфікації типу функції (@spec). Потрібно вказати назву функції, список типів аргументів і всі можливі типи повернених значень.

defmodule Countable do
  @callback count(collection :: any) :: pos_integer
end

Реалізація поведінок

Щоб додати наявну поведінку до нашого модуля (створити модуль-колбек), ми використовуємо атрибут модуля @behaviour. Його значенням має бути назва модуля поведінки, яку ми додаємо.

Потім потрібно визначити всі функції (колбеки), які вимагає цей модуль поведінки. Якщо ми реалізуємо чужу поведінку, наприклад вбудовані поведінки Elixir Access або GenServer, список усіх колбеків цієї поведінки можна знайти в документації на hexdocs.pm.

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

Щоб позначити, яка функція походить з якої поведінки, слід використовувати атрибут модуля @impl перед кожною функцією. Його значенням має бути назва модуля поведінки, що визначає цей колбек.

defmodule BookCollection do
  @behaviour Countable

  defstruct [:list, :owner]

  @impl Countable
  def count(collection) do
    Enum.count(collection.list)
  end

  def mark_as_read(collection, book) do
    # other function unrelated to the Countable behaviour
  end
end

Типові реалізації колбеків

Визначаючи поведінку, можна надати типову реалізацію колбека. Цю реалізацію слід визначити в цитованому виразі макроса __using__/1. Щоб користувачі модуля поведінки могли перевизначити типову реалізацію, потрібно викликати макрос defoverridable/1 після реалізації функції. Він приймає ключовий список, у якому ключами є назви функцій, а значеннями - їхні арності.

defmodule Countable do
  @callback count(collection :: any) :: pos_integer

  defmacro __using__(_) do
    quote do
      @behaviour Countable
      def count(collection), do: Enum.count(collection)
      defoverridable count: 1
    end
  end
end

Варто зауважити, що визначати функції всередині __using__/1 не рекомендується для будь-якої іншої мети, ніж визначення типових реалізацій колбеків, але функції завжди можна визначити в іншому модулі та імпортувати їх у макросі __using__/1.

Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Поведінки