灵丹妙药中的协议有什么意义?

Bal*_*ala 2 elixir

在使用网络协议(http、ftp 等)这个术语后,我对它在 Elixir 中的用法感到困惑。例如,有对 Enum 模块和 Enumerable Protocol 的引用。Elixir 文档说Protocols are a mechanism to achieve polymorphism in Elixir

它们不只是具有一组方法/功能的模块吗?有什么区别吗?

Ale*_*kin 5

将协议视为 Java 中的接口/Python 中的抽象类(实际上,Java 接口,特别是 Python 抽象类更像是@behaviour,但无论如何。)

defprotocol Sound do
  def make_sound(data)
end

defmodule Dog do
  defstruct name: "Donny"
end

defimpl Sound, for: Dog do
  def make_sound(data) do
    "#{data.name} barks “woof”"
  end
end

defmodule Cat do
  defstruct name: "Hilly"
end

defimpl Sound, for: Cat do
  def make_sound(data) do
    "#{data.name} murrs “meow”"
  end
end
Run Code Online (Sandbox Code Playgroud)

在代码中:

%Dog{} |> Sound.make_sound
#? "Donny barks “woof”"
Run Code Online (Sandbox Code Playgroud)

或者:

pet = .... # complicated code loading a struct
pet |> Sound.make_sound # here we don’t care what pet we have
Run Code Online (Sandbox Code Playgroud)

这种机制用于字符串插值:

"#{5}"
Run Code Online (Sandbox Code Playgroud)

上面的工作是因为IntegerString.Chars. 实现只是调用

WHATEVER_IN_#{} |> String.Chars.to_string
Run Code Online (Sandbox Code Playgroud)

得到一个二进制文件。例如。对于上述Dog模块,我们可能会实现String.Chars

defimpl String.Chars, for: Dog do
  def to_string(term) do
    "#{term.name} barks “woof”"
  end
end
Run Code Online (Sandbox Code Playgroud)

现在可以插入狗:

"#{%Dog{}}"
#? "Donny barks “woof”"
Run Code Online (Sandbox Code Playgroud)