2014-10-06 105 views
28

行为定义回调&协议定义了没有签名的方法。实施协议的模块应给出所有这些方法的定义。对于使用行为的模块也是如此。什么是语义差异?elixir中的协议和行为之间的区别

我能想到的一个区别是,一个协议只能针对单一类型实现一次,因为我们可以根据我们的要求多次实现模块的行为。我很清楚什么时候该用什么。除此之外是否还有其他区别?

+4

此外,最重要的是,行为启动新的进程,其中运行回调而协议功能在同一进程中运行。这与下面的评论相同,但经常被忽略。行为隐藏了所有的并发和消息传递,但它们仍然存在,客户端调用和回调调用在不同的进程中运行。 – rvirding 2014-10-09 00:16:00

+1

@rvirding我不知道它,我不记得在任何书或教程中看到。有没有关于行为如何隐式地启动新流程的文档或任何其他文章的任何部分? – 2016-04-15 10:01:37

+0

@KrzysztofWende它隐含在http://erlang.org/doc/design_principles/des_princ.html中。基本上,“行为”一词与OTP应用程序有很大的关系,因此也涉及监督树木的维护过程。在Erlang中,一种行为将常见模式(客户端服务器,状态机等)抽象出来,以便您不必手动调用spawn *和模式匹配消息(这很容易出错)。弗雷德赫伯特的在线教程帮助我了解了很多:http://learnyousomeerlang.com/what-is-otp#the-common-process-abstracted – 2017-06-16 19:33:58

回答

30

协议是基于类型/数据的多态性。当我打电话给Enum.each(foo, ...)时,具体列举由foo的类型确定。

行为是一种无类型的插件机制。当我致电GenServer.start(MyModule)时,我明确地通过MyModule作为插件,并且GenServer的通用代码将在需要时调用此模块。

+5

此外,最重要的是,行为启动新的进程,其中回调运行协议功能在相同的过程中运行。 – rvirding 2014-10-08 13:39:00

+6

@rvirding你错了。行为只是描述了模块中必须存在的功能。他们对流程没有做任何事情。 – rightfold 2015-05-24 23:15:48

+1

@rightfold ok,那么elixir具有与erlang不同的行为含义,这可能会让人困惑,因为它们也使用erlang行为。你可以说erlang的行为描述了接口函数,但是更多的是它的基础,它们都是函数接口的进程的属性。有进程就是erlang行为的全部内容。 – rvirding 2015-05-26 11:12:43

13

通过JoséValim上同一主题的回答(从谷歌螺纹,https://groups.google.com/forum/#!msg/elixir-lang-talk/S0NlOoc4ThM/J2aD2hKrtuoJ

协议是确实是一个行为+调度逻辑。

但是我认为你错过了行为的要点。行为 是非常有用的。例如,GenServer定义了一个行为。 A 行为是一种说法:给我一个模块作为参数,我会 对它调用以下回调,这些参数等等。 适用于除GenServer外的其他行为的更复杂示例是Ecto 适配器。

但是,如果您有数据结构并且您希望 基于数据结构进行分派,则这不起作用。因此协议。