请告知:Erlang有什么方法可以将合同中的实现分开,以及如何在合同之间切换?
感谢您的提示! YF
答案 0 :(得分:2)
多态性的好例子是qlc
模块和结构table
。请参阅M:table/1,2
,ets
,dets
等各种mnesia
实施。以shell中的ets:table(ets:new(foo, [set])).
为例,查看qlc
文档和示例。
答案 1 :(得分:1)
由于Erlang是动态类型的,function guards(when … ->
位)是表达多态的方式。
E.g:
len (T) when is_tuple(T) -> size(T);
len (L) when is_list(L) -> length(L).
答案 2 :(得分:1)
也许看看behaviours概念。至少就我而言,在具有接口定义和多个实现模块方面与OOP的相似性很小。
答案 3 :(得分:1)
虽然其他人提到行为功能,但它只是一个小帮手,可确保您在模块中实现回调结构的所有功能。如果您有两个实现a
和b
,并且两者都实现了相同的功能,则可以在调用模块中静态替换a
b
。对于具有更好实现的静态配置,这是更可取的。
如果问题更具动态性,您可以这样做
Mod = a,
Mod:f(Args).
然后在代码集Mod
中进行适当的处理。这使您可以动态控制程序运行时要调用的模块。你想要的两个中哪一个并不完全清楚。
答案 4 :(得分:0)
如果我意识到你的问题,这里是方法的例子,那对我来说非常有用。这种方法有助于分离界面和实现。
“界面”模块。
-module(contract).
-export([
new/2,
do_something/2
]).
%% Behavioural callbacks definition. Each of "derived" modules should implement it.
-callback new(Arg :: any()) -> {ok, ImplState :: any()} | {error, Reason :: atom()}.
-callback do_something( Arg :: any(), ImplState :: any() ) -> {ok, ReturnVal :: any(), NewImplState :: any()} | {error, Reason :: atom()}.
%% Opaque state to hold implementation details
-record(
contract_impl, {
impl_module :: module(),
impl_state :: any()
}
).
%% Interface for creation "polymorphic" instance, like base-class constructor.
new(ImplModule, ImplInitArgs) ->
case ImplModule:new(ImplInitArgs) of
{ok, State} ->
{ok,
#contract_impl {
impl_module = ImplModule,
impl_state = State
}
};
{error, Reason} ->
{error, Reason}
end.
%% Interface function, like an abstract method in OOP.
do_something(
Arg,
#contract_impl {
impl_module = ImplModule,
impl_state = ImplState
} = ContractImpl
) ->
case ImplModule:do_something(Arg, ImplState) of
{ok, ReturnVal, NewState} ->
{ok, ReturnVal, ContractImpl#contract_impl{ impl_state = NewState }};
{error, Reason} -> {error, Reason}
end.
一些实现示例(如派生类)。
-module(foo).
-behaviour(contract).
-export([
new/1,
do_something/2
]).
-record(
foo_state, {
repeat_count
}
).
new(Options) ->
{ok,
#foo_state{
repeat_count = proplists:get_value(repeat_count, Options)
}
}.
do_something(Arg, #foo_state{ repeat_count = RepeatCount } = State) ->
Result = [ io_lib:format("Foo ~p", [Arg]) || _Index <- lists:seq(1, RepeatCount) ],
{ok, Result, State}.
现在您可以执行以下操作:
usage_example() ->
{ok, State} = contract:new(foo, [{repeat_count, 15}]),
{ok, Result, NewState} = contract:do_something("bar", State),
ok.
我希望这会有所帮助。