当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


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