Elixir模块属性 #

一、属性基础 #

1.1 定义属性 #

elixir
defmodule Example do
  @name "MyModule"
  @version "1.0.0"

  def info do
    "Module: #{@name}, Version: #{@version}"
  end
end

1.2 读取属性 #

elixir
iex(1)> defmodule Example do
...>   @value 42
...>   def get_value, do: @value
...> end

iex(2)> Example.get_value()
42

1.3 属性特性 #

  • 属性在编译时求值
  • 属性值在编译后不可变
  • 每次读取属性都会内联其值

二、内置属性 #

2.1 文档属性 #

elixir
defmodule User do
  @moduledoc """
  User management module.

  This module provides functions for managing users.
  """

  @doc """
  Creates a new user.

  ## Parameters

    - `name` - User name
    - `email` - User email

  ## Examples

      iex> User.new("Alice", "alice@example.com")
      %User{name: "Alice", email: "alice@example.com"}

  """
  def new(name, email) do
    %{name: name, email: email}
  end
end

2.2 类型属性 #

elixir
defmodule User do
  @type t :: %__MODULE__{
    id: integer(),
    name: String.t(),
    email: String.t()
  }

  @type name :: String.t()
  @type email :: String.t()

  defstruct [:id, :name, :email]
end

2.3 规范属性 #

elixir
defmodule Math do
  @spec add(number(), number()) :: number()
  def add(a, b), do: a + b

  @spec divide(number(), number()) :: {:ok, number()} | {:error, :division_by_zero}
  def divide(_, 0), do: {:error, :division_by_zero}
  def divide(a, b), do: {:ok, a / b}
end

2.4 行为属性 #

elixir
defmodule MyGenServer do
  @behaviour GenServer

  def init(args), do: {:ok, args}
  def handle_call(_msg, _from, state), do: {:reply, :ok, state}
  def handle_cast(_msg, state), do: {:noreply, state}
end

三、累积属性 #

3.1 累积列表 #

elixir
defmodule Router do
  @routes []

  def route(path, handler) do
    @routes [{path, handler} | @routes]
  end

  def routes, do: @routes
end

3.2 注册回调 #

elixir
defmodule Plugin do
  @callbacks []

  def register_callback(name, func) do
    @callbacks [{name, func} | @callbacks]
  end

  def callbacks, do: @routes
end

3.3 使用示例 #

elixir
defmodule MyPlugin do
  Plugin.register_callback(:before_save, fn data -> data end)
  Plugin.register_callback(:after_save, fn data -> IO.puts("Saved") end)
end

四、编译时钩子 #

4.1 @before_compile #

elixir
defmodule MyModule do
  @before_compile MyModule

  defmacro __before_compile__(_env) do
    quote do
      def generated_function, do: "I was generated!"
    end
  end
end

4.2 @after_compile #

elixir
defmodule MyModule do
  @after_compile __MODULE__

  def __after_compile__(_env, _bytecode) do
    IO.puts("Module compiled!")
  end
end

4.3 @on_definition #

elixir
defmodule Tracer do
  @on_definition {Tracer, :trace}

  def trace(_env, :def, name, args, _guards, _body) do
    IO.puts("Defined function #{name}/#{length(args)}")
  end

  def trace(_env, :defp, name, args, _guards, _body) do
    IO.puts("Defined private function #{name}/#{length(args)}")
  end

  def trace(_, _, _, _, _, _), do: :ok

  def public_func(a, b), do: a + b
  defp private_func(a), do: a * 2
end

五、外部资源 #

5.1 @external_resource #

elixir
defmodule Config do
  @external_resource Path.join([__DIR__, "config.json"])

  @config File.read!(Path.join([__DIR__, "config.json"]))
          |> Jason.decode!()

  def get(key), do: Map.get(@config, key)
end

5.2 重新编译 #

当外部资源改变时,模块会重新编译。

六、编译选项 #

6.1 @compile #

elixir
defmodule Optimized do
  @compile {:inline, my_func: 1}

  def my_func(x), do: x * 2
end

6.2 常用选项 #

elixir
@compile :nowarn_unused_vars
@compile {:nowarn_unused_vars, true}
@compile {:inline, func: 1}
@compile {:autoload, false}

七、模块信息 #

7.1 获取模块信息 #

elixir
iex(1)> defmodule Example do
...>   @author "Developer"
...>   def info, do: __MODULE__.__info__(:attributes)
...> end

iex(2)> Example.info()
[author: "Developer"]

7.2 __info__选项 #

elixir
__MODULE__.__info__(:functions)
__MODULE__.__info__(:macros)
__MODULE__.__info__(:module)
__MODULE__.__info__(:attributes)
__MODULE__.__info__(:compile)

八、属性最佳实践 #

8.1 常量定义 #

elixir
defmodule Constants do
  @pi 3.14159265359
  @e 2.71828182846
  @golden_ratio 1.61803398875

  def pi, do: @pi
  def e, do: @e
  def golden_ratio, do: @golden_ratio
end

8.2 配置管理 #

elixir
defmodule AppConfig do
  @app_name Application.compile_env(:my_app, :name, "MyApp")
  @version Application.compile_env(:my_app, :version, "0.1.0")
  @env Application.compile_env(:my_app, :env, :dev)

  def app_name, do: @app_name
  def version, do: @version
  def env, do: @env
end

8.3 元数据注册 #

elixir
defmodule Task do
  @tasks %{}

  def register(name, func) do
    @tasks Map.put(@tasks, name, func)
  end

  def get(name), do: Map.get(@tasks, name)

  def all, do: @tasks
end

九、属性列表 #

属性 用途
@moduledoc 模块文档
@doc 函数文档
@spec 类型规范
@type 类型定义
@typep 私有类型
@opaque 不透明类型
@callback 回调规范
@macrocallback 宏回调
@behaviour 行为实现
@before_compile 编译前钩子
@after_compile 编译后钩子
@on_definition 定义钩子
@external_resource 外部资源
@compile 编译选项
@derive 协议派生
@enforce_keys 强制键

十、总结 #

本章学习了:

特性 用途
自定义属性 存储常量和元数据
累积属性 收集多个值
编译钩子 编译时代码生成
内置属性 文档、类型、规范

准备好学习并发编程了吗?让我们进入下一章。

最后更新:2026-03-27