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 Kernel.defexception用法及代碼示例
- Elixir Kernel.defmodule用法及代碼示例
- Elixir Kernel.defmacro用法及代碼示例
- Elixir Kernel.defdelegate用法及代碼示例
- Elixir Kernel.defguard用法及代碼示例
- Elixir Kernel.defoverridable用法及代碼示例
- Elixir Kernel.defp用法及代碼示例
- Elixir Kernel.def用法及代碼示例
- Elixir Kernel.destructure用法及代碼示例
- Elixir Kernel.div用法及代碼示例
- Elixir Kernel.SpecialForms.case用法及代碼示例
- Elixir Kernel.round用法及代碼示例
- Elixir Kernel.left / right用法及代碼示例
- Elixir Kernel.put_in用法及代碼示例
- Elixir Kernel.tl用法及代碼示例
- Elixir Kernel.left - right用法及代碼示例
- Elixir Kernel.tuple_size用法及代碼示例
- Elixir Kernel.to_charlist用法及代碼示例
- Elixir Kernel.base ** exponent用法及代碼示例
- Elixir Kernel.left !== right用法及代碼示例
- Elixir Kernel.if用法及代碼示例
- Elixir Kernel.spawn_monitor用法及代碼示例
- Elixir Kernel.to_string用法及代碼示例
- Elixir Kernel.length用法及代碼示例
- Elixir Kernel.first..last用法及代碼示例
注:本文由純淨天空篩選整理自elixir-lang.org大神的英文原創作品 Kernel.defstruct(fields)。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。