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)。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。