Elixir Protocols(协议)

定义

协议是一种在 Elixir 中实现多态的机制。之前的解决方法是:模式匹配和 Guard 子句

使用defprotocol来定义协议,使用defimpl来添加任意数量的实现,@spec 定义了类型规范

defprotocol Utility do
  @spec type(t) :: String.t()
  def type(value)
end

defimpl Utility, for: BitString do
  def type(_value), do: "string"
end

defimpl Utility, for: Integer do
  def type(_value), do: "integer"
end

可以为所有 Elixir 数据类型实现协议。

Atom
BitString
Float
Function
Integer
List
Map
PID
Port
Reference
Tuple

Protocols and structs

协议与结构体一起使用,就可以发挥出它的强大力量。

defmodule User do
  defstruct [:name, :age]
end

defimpl Size, for: User do
  def size(_user), do: 2
end

实现 Any

手动为所有类型实现协议会变得很乏味。Elixir 提供了两种选择可以为 Any 实现协议。

defimpl Size, for: Any do
  def size(_), do: 0
end

Deriving

使用@derive显式派生协议,对于非 structs 来说不好处理

defmodule OtherUser do
  @derive [Size]
  defstruct [:name, :age]
end

Fallback to Any

通过指定@fallback_to_anytrue,可以实现任何数据类型

defprotocol Size do
  @fallback_to_any true
  def size(data)
end

示例代码:
https://github.com/KINGMJ/elixir-learning/tree/elixir-practice/7.AreaProtocal