行为定义回调&协议定义没有签名的方法。实现协议的模块应该为所有这些方法提供定义。使用行为的模块也是如此。什么是语义差异?
我能想到的一个区别是,协议只能针对单一类型实现一次,因为我们可以根据我们的要求多次实现模块的行为。我很清楚何时使用什么。除此之外还有其他区别吗?
答案 0 :(得分:37)
协议是基于类型/数据的多态性。当我调用Enum.each(foo, ...)
时,具体的枚举是根据foo
的类型确定的。
行为是一种无类型的插件机制。当我致电GenServer.start(MyModule)
时,我明确地将MyModule
作为插件传递,来自GenServer
的通用代码会在需要时调用此模块。
答案 1 :(得分:21)
JoséValim对同一主题的回答(来自谷歌主题,https://groups.google.com/forum/#!msg/elixir-lang-talk/S0NlOoc4ThM/J2aD2hKrtuoJ)
协议确实是一种行为+调度逻辑。
但是我认为你错过了行为的观点。行为 非常有用。例如,GenServer定义了一种行为。一个 行为是一种说法:给我一个模块作为参数,我会 在它上面调用以下回调,这些参数等等。 除了GenServer之外,更复杂的行为示例是Ecto 适配器。
但是,如果您有自己想要的数据结构,则不起作用 根据数据结构进行调度。因此协议。