Sie sind sehr nah dran. Es ist tatsächlich einfacher als das, was Sie versucht haben:
Der Compiler kann das vollständig verstehen, so wie es ist.
So einfach, seine Art von Antiklimak.
EDIT
"Cool Geschichte, wie zu benutzen?"
Nichts spricht wie ein funktionierendes Beispiel:
Hier haben wir einen abstrakten Service. Es soll auf ein sehr enges Nachrichtenspektrum reagieren und alles andere lächerlich machen. Sein spezielles Element ist jedoch, dass es als Start-Argument den Namen eines Moduls akzeptiert, das einen bestimmten Aspekt von sein Verhalten definiert - und dies ist das Callback-Modul.
-module(my_abstract).
-export([start/1]).
start(CallbackMod)->
spawn(fun() -> loop(CallbackMod) end).
loop(CBM) ->
receive
{Sender, {do_it, A}} ->
Sender ! CBM:fn(A),
loop(CBM);
stop ->
io:format("~p (~p): Farewell!~n",
[self(), ?MODULE]);
Message ->
io:format("~p (~p): Received silliness: ~tp~n",
[self(), ?MODULE, Message]),
loop(CBM)
end.
hier So definieren wir einen wirklich einfachen Callback-Modul, in Übereinstimmung mit dem Verhalten wie 'my_behavior'
oben definiert:
-module(my_callbacks).
-behavior(my_behavior).
-export([fn/1]).
fn(A) -> A + 1.
Hier ist es in Aktion!
1> c(my_behavior).
{ok,my_behavior}
2> c(my_abstract).
{ok,my_abstract}
3> c(my_callbacks).
{ok,my_callbacks}
4> Service = my_abstract:start(my_callbacks).
<0.50.0>
5> Service ! {self(), {do_it, 5}}.
{<0.33.0>,{do_it,5}}
6> flush().
Shell got 6
ok
7> Service ! {self(), {do_it, 41}}.
{<0.33.0>,{do_it,41}}
8> flush().
Shell got 42
ok
9> Service ! stop.
<0.50.0> (my_abstract): Farewell!
stop
Also was ist die Verhaltensdefinition gut? Es tat nicht wirklich tun alles! Nun, was nützen all diese Dialyzer-Typ-Hierarchiedeklarationen? Sie tun auch nichts.Aber sie helfen Ihnen, Ihre Arbeit automatisch zu überprüfen, um sicherzustellen, dass Sie keinen aufregenden Runtime-Fehler erleben - aber weder Dialyzer noch Verhaltensdefinitionen zwingen Sie zu etwas: Sie warnen uns lediglich vor unserem (wahrscheinlich) bevorstehenden Untergang:
-module(my_other_callbacks).
-behavior(my_behavior).
-export([haha_wtf/1]).
haha_wtf(A) -> A - 1.
und wenn wir das bauen wir erhalten:
10> c(my_other_callbacks).
my_other_callbacks.erl:2: Warning: undefined callback function fn/1 (behaviour 'my_behavior')
{ok,my_other_callbacks}
Beachten Sie jedoch, dass dieses Modul war tatsächlich kompiliert und ist nach wie vor unabhängig nutzbar (aber nicht von unserem abstrakten Service, der fn/1
zu finden erwartet definiert in irgendetwas genannt my_behavior
):
11> my_other_callbacks:haha_wtf(5).
4
Hoffentlich wirft diese kleine Walktour etwas Licht auf den Pfad.
Eigentlich muss ich die Funktion apply_fn (jetzt add_one) zu arbeiten. Ich habe das Beispiel angepasst, um es klarer zu machen. –
@ JörgenBrandt OK, ein bisschen Bearbeitung dort ... Das ist nicht schwer zu verstehen, aber um wirklich grok zu werden, benötigt man ein komplettes Beispiel, wenn man es zum ersten Mal sieht. – zxq9
Danke für die bisherige Mühe. Sollte es nicht -module (my_behaviour) sein. in der ersten Zeile des ersten Snippets? Oder fehlt mir etwas? –