在Erlang中编写和编译自定义行为

时间:2015-01-13 10:49:27

标签: erlang

我正在尝试在Erlang中编写和编译自定义行为

我找不到有关如何编译此行为的任何明确文档。

-module(bla).

-export([start_link/0,behaviour_info/1]).

behaviour_info(callbacks)->
    [{init,1}];
behaviour_info(_Other)->
    undefined.

%% -callback init(Args :: term()) ->
%%     {ok, State :: term()} | {ok, State :: term(), timeout()} |
%%     {stop, Reason :: term()} | ignore.

start_link()->
    init([]).

我的通讯命令是:

erlc.exe .\src\bla.erl

所得:

bla.erl:24: function init/1 undefined

有人想知道在erlang中编写和编译行为吗?任何链接?

1 个答案:

答案 0 :(得分:2)

定义行为回调会导致您实施回调模块的义务。在erlang中,模块只是函数容器,而不是类和接口。行为基于运行时模块名称解析Mod:fun()。 OTP gen_server(检查它)在您将其传递回来后保留其回调模块名称:gen_server:start_link(CallbackModuleName, Args, Opts)这里是applying callback init/1的代码:

init_it(Starter, Parent, Name0, Mod, Args, Options) ->
    Name = name(Name0),
    Debug = debug_options(Name, Options),
    case catch Mod:init(Args) of
        {ok, State} ->
            proc_lib:init_ack(Starter, {ok, self()}),
            loop(Parent, Name, State, Mod, infinity, Debug);
        {ok, State, Timeout} ->
            proc_lib:init_ack(Starter, {ok, self()}),
            loop(Parent, Name, State, Mod, Timeout, Debug);
        ...

它应用init/1传递的回调模块保存在Mod参数中,获取其最后一个值,执行您想要的操作并继续(或不执行,取决于最后一个值)。

假设我们有模块bla_impl,如下所示:

-module(bla_impl).
-behaviour(bla).
-export([init/1, start_link/0]).

start_link() -> bla:start_link(?MODULE). %% macro ?MODULE is resolved to bla_impl
init(Args) -> ... .

现在你需要在bla中说出你使用的模块:

-module(bla).
-export([start_link/1]).

start_link(Mod) -> Mod:init([]).

或者更好的解决方案是从配置中读取它:

-module(bla).
-export([start_link/0]).

start_link() -> 
    Mod = application:get_env(bla_app,  callback_module),
    Mod:init([]),
    ...

有很多方法可以这样做。

如你所见,这里没有魔力。即使没有-behaviour(bla)也没有使用-callback指定回调,这也可以使用。这只是编译器,工具和文档的信息。

来自erlang文档:Behaviours

顺便说一下。 start_link函数应该生成另一个进程并链接到它。

start_link(Mod) ->
    spawn_link(Mod, init, [[]]).