Elixir 协议

2023-12-15 14:57 更新
  1. 协议与结构体
  2. 执行​Any
    1. 派生
    2. 回退到​Any
  3. 内置协议
  4. 协议巩固

协议是Elixir中用于达到多态性的一个机制.任何数据类型只要实现了协议,就可以基于协议被调度.让我们来看一个例子.

在Elixir中,只有falsenil为假.任何其他东西都为真.对应用来说,设定一个返回布尔值的blank?协议来判断其它数据类型是否为空也许十分重要.事实上,一个空的列表或一个空的二进制数会被认为是空的.

我们能够这样定义协议:

defprotocol Blank do
  @doc "Returns true if data is considered blank/empty"
  def blank?(data)
end

该协议需要一个名为​blank?​的函数,它接受一个参数.我们可以为其它Elixir数据类型实现这个协议:

# 整数不可能为空白
defimpl Blank, for: Integer do
  def blank?(_), do: false
end

# 空的列表是空白
defimpl Blank, for: List do
  def blank?([]), do: true
  def blank?(_),  do: false
end

# 空的映射是空白
defimpl Blank, for: Map do
  # 记住我们不能用%{}来模式匹配
  # 它能匹配所有映射.但我们可以判断映射大小是否
  # 为零(而且计算大小是一个快速操作).
  def blank?(map), do: map_size(map) == 0
end

# 原子false和nil是空白
defimpl Blank, for: Atom do
  def blank?(false), do: true
  def blank?(nil),   do: true
  def blank?(_),     do: false
end

我们为所有原始数据类型都这样做了.这些类型有:

Atom
BitString
Float
Function
Integer
List
Map
PID
Port
Reference
Tuple

协议和实现都已经定义好,我们可以调用它了:

iex> Blank.blank?(0)
false
iex> Blank.blank?([])
true
iex> Blank.blank?([1, 2, 3])
false

传递了一个协议没有实现的数据类型将会抛出一个错误:

iex> Blank.blank?("hello")
** (Protocol.UndefinedError) protocol Blank not implemented for "hello"


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号