Erlang Language
поведения
Поиск…
Использование поведения
Добавьте директиву -behaviour
в свой модуль, чтобы указать, что он следует за поведением:
-behaviour(gen_server).
Американское правописание также принято:
-behavior(gen_server).
Теперь компилятор даст предупреждение, если вы забыли реализовать и экспортировать любую из функций, требуемых поведением, например:
foo.erl:2: Warning: undefined callback function init/1 (behaviour 'gen_server')
Определение поведения
Вы можете определить свое поведение, добавив в свой модуль директивы -callback
. Например, если модули, реализующие ваше поведение, должны иметь функцию foo
которая принимает целое число и возвращает атом:
-module(my_behaviour).
-callback foo(integer()) -> atom().
Если вы используете это поведение в другом модуле, компилятор будет предупреждать, если он не экспортирует foo/1
, и Dialyzer будет предупреждать, если типы неверны. С помощью этого модуля:
-module(bar).
-behaviour(my_behaviour).
-export([foo/1]).
foo([]) ->
{}.
и работает dialyzer --src bar.erl my_behaviour.erl
, вы получаете следующие предупреждения:
bar.erl:5: The inferred type for the 1st argument of foo/1 ([]) is not a supertype of integer(), which is expected type for this argument in the callback of the my_behaviour behaviour
bar.erl:5: The inferred return type of foo/1 ({}) has nothing in common with atom(), which is the expected return type for the callback of my_behaviour behaviour
Необязательные обратные вызовы в пользовательском поведении
По умолчанию любая функция, указанная в директиве -callback
в модуле поведения, должна быть экспортирована модулем, который реализует это поведение. В противном случае вы получите предупреждение о компиляторе.
Иногда вы хотите, чтобы функция обратного вызова была необязательной: поведение будет использовать ее, если она присутствует и экспортируется, и в противном случае отказываться от реализации по умолчанию. Для этого напишите директиву -callback
как обычно, а затем перечислите функцию обратного вызова в директиве -optional_callbacks
:
-callback bar() -> ok.
-optional_callbacks([bar/0]).
Если модуль экспортирует bar/0
, Dialyzer по-прежнему будет проверять спецификацию типа, но если функция отсутствует, вы не получите предупреждение о компиляторе.
В самой Erlang / OTP, это делается для format_status
функции обратного вызова в gen_server
, gen_fsm
и gen_event
поведения.