Elixir 協(xié)議

2023-12-15 14:57 更新
  1. 協(xié)議與結(jié)構(gòu)體
  2. 執(zhí)行?Any ?
    1. 派生
    2. 回退到?Any?
  3. 內(nèi)置協(xié)議
  4. 協(xié)議鞏固

協(xié)議是Elixir中用于達(dá)到多態(tài)性的一個(gè)機(jī)制.任何數(shù)據(jù)類型只要實(shí)現(xiàn)了協(xié)議,就可以基于協(xié)議被調(diào)度.讓我們來看一個(gè)例子.

在Elixir中,只有falsenil為假.任何其他東西都為真.對(duì)應(yīng)用來說,設(shè)定一個(gè)返回布爾值的blank?協(xié)議來判斷其它數(shù)據(jù)類型是否為空也許十分重要.事實(shí)上,一個(gè)空的列表或一個(gè)空的二進(jìn)制數(shù)會(huì)被認(rèn)為是空的.

我們能夠這樣定義協(xié)議:

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

該協(xié)議需要一個(gè)名為?blank??的函數(shù),它接受一個(gè)參數(shù).我們可以為其它Elixir數(shù)據(jù)類型實(shí)現(xiàn)這個(gè)協(xié)議:

# 整數(shù)不可能為空白
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
  # 記住我們不能用%{}來模式匹配
  # 它能匹配所有映射.但我們可以判斷映射大小是否
  # 為零(而且計(jì)算大小是一個(gè)快速操作).
  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

我們?yōu)樗性紨?shù)據(jù)類型都這樣做了.這些類型有:

Atom
BitString
Float
Function
Integer
List
Map
PID
Port
Reference
Tuple

協(xié)議和實(shí)現(xiàn)都已經(jīng)定義好,我們可以調(diào)用它了:

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

傳遞了一個(gè)協(xié)議沒有實(shí)現(xiàn)的數(shù)據(jù)類型將會(huì)拋出一個(gè)錯(cuò)誤:

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


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)