Elixir - 协议

协议是 Elixir 中实现多态性的一种机制。 只要实现该协议,任何数据类型都可以在协议上进行调度。

让我们考虑一个使用协议的示例。 我们在前面的章节中使用了一个名为 to_string 的函数来从其他类型转换为字符串类型。 这实际上是一个协议。 它根据给出的输入进行操作,不会产生错误。 这看起来像是我们正在讨论模式匹配函数,但随着我们进一步深入,结果却有所不同。

考虑以下示例以进一步了解协议机制。

让我们创建一个协议,该协议将显示给定的输入是否为空。 我们将此协议称为blank?

定义协议

我们可以通过以下方式在 Elixir 中定义协议 −

defprotocol Blank do
   def blank?(data)
end

如您所见,我们不需要为函数定义主体。 如果您熟悉其他编程语言中的接口,您可以将协议视为本质上相同的东西。

所以这个协议是说任何实现它的东西都必须有一个empty?函数,尽管函数如何响应取决于实现者。 定义协议后,让我们了解如何添加几个实现。

实现协议

既然我们已经定义了一个协议,我们现在需要告诉它如何处理它可能获得的不同输入。 让我们以之前的例子为基础。 我们将为列表、映射和字符串实施空白协议。 这将显示我们传递的内容是否为空。

#定义协议
defprotocol Blank do
   def blank?(data)
end

#实现列表协议
defimpl Blank, for: List do
   def blank?([]), do: true
   def blank?(_), do: false
end

#实现字符串协议
defimpl Blank, for: BitString do
   def blank?(""), do: true
   def blank?(_), do: false
end

#实现映射协议
defimpl Blank, for: Map do
   def blank?(map), do: map_size(map) == 0
end

IO.puts(Blank.blank? [])
IO.puts(Blank.blank? [:true, "Hello"])
IO.puts(Blank.blank? "")
IO.puts(Blank.blank? "Hi")

您可以根据需要实现任意数量的协议,只要对协议的使用有意义即可。 这是协议的一个非常基本的用例。 当上面的程序运行时,它会产生以下结果 −

true
false
true
false

注意 − 如果您将此用于定义协议之外的任何类型,则会产生错误。