當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Elixir Kernel.defstruct用法及代碼示例


Elixir語言中 Kernel.defstruct 相關用法介紹如下。

用法:

defstruct(fields)
(宏)

定義一個結構。

結構是一個標記的映射,它允許開發人員為鍵提供默認值,標簽用於多態調度和編譯時斷言。有關結構的更多信息,請查看 Kernel.SpecialForms.%/2

隻能為每個模塊定義一個結構,作為它綁定到模塊本身的結構。調用 defstruct/1 還定義了一個返回結構本身的__struct__/0 函數。

例子

defmodule User do
  defstruct name: nil, age: nil
end

結構字段在編譯時進行評估,這允許它們是動態的。在下麵的示例中,10 + 11 在編譯時進行評估,並且年齡字段與值 21 一起存儲:

defmodule User do
  defstruct name: nil, age: 10 + 11
end

fields 參數通常是一個關鍵字列表,其中字段名稱作為原子鍵,默認值作為對應值。 defstruct/1 還支持原子列表作為其參數:在這種情況下,列表中的原子將用作結構的字段名稱,並且它們都將默認為 nil

defmodule Post do
  defstruct [:title, :content, :author]
end

導出

盡管結構是映射,但默認情況下結構不實現為映射實現的任何協議。例如,嘗試使用帶有 User 結構的協議會導致錯誤:

john = %User{name: "John"}
MyProtocol.call(john)
** (Protocol.UndefinedError) protocol MyProtocol not implemented for %User{...}

但是, defstruct/1 允許協議實現為 derived 。這可以通過在調用 defstruct/1 之前將 @derive 屬性定義為列表來完成:

defmodule User do
  @derive [MyProtocol]
  defstruct name: nil, age: 10 + 11
end

MyProtocol.call(john) # it works!

對於 @derive 列表中的每個協議,Elixir 將斷言該協議已為 Any 實現。如果 Any 實現定義了 __deriving__/3 回調,則將調用回調並且它應該定義實現模塊。否則,將自動派生僅指向 Any 實現的實現。有關 __deriving__/3 回調的更多信息,請參閱 Protocol.derive/3

強製執行 key

在構建結構體時,Elixir 會自動保證所有鍵都屬於該結構體:

%User{name: "john", unknown: :key}
** (KeyError) key :unknown not found in: %User{age: 21, name: nil}

Elixir 還允許開發人員強製在構建結構時必須始終給出某些鍵:

defmodule User do
  @enforce_keys [:name]
  defstruct name: nil, age: 10 + 11
end

現在嘗試構建沒有 name 鍵的結構將失敗:

%User{age: 21}
** (ArgumentError) the following keys must also be given when building struct User: [:name]

請記住,@enforce_keys 是一個簡單的編譯時保證,可在構建結構時幫助開發人員。它不對更新強製執行,也不提供任何類型的value-validation。

類型

建議為結構定義類型。按照慣例,這種類型稱為 t 。要在類型中定義結構,使用結構字麵量語法:

defmodule User do
  defstruct name: "John", age: 25
  @type t :: %__MODULE__{name: String.t(), age: non_neg_integer}
end

建議在定義結構的類型時隻使用結構語法。當引用另一個結構時,最好使用 User.t 而不是 %User{}

%User{} 中未包含的結構字段的類型默認為term()(請參閱 term/0 )。

內部結構為本地模塊私有的結構(不應允許模式匹配它們或直接訪問它們的字段)應使用@opaque 屬性。內部結構為公共的結構應使用 @type

相關用法


注:本文由純淨天空篩選整理自elixir-lang.org大神的英文原創作品 Kernel.defstruct(fields)。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。