簡単なWebフレームワークを作ってみようと、Plugやtrotを読んでいると、いたるところで @behaviour と描かれているものがありました。
GenServer なんかを use した時にOTPとしての振る舞いを、対象モジュールに与えることができました。そこで使われている Behaviour は把握していたのですが、この @ のアノテーションはパッと思い出すことができなかったので、メモがてら。
Elixir 1.2.xの時点が対象です。結論から書いておくと、この @behaviour は Behaviour のことで、2.0では削除される Behaviour の代わりに推奨されているものです。
- ドキュメント
- https://github.com/elixir-lang/elixir/blob/v1.2/lib/elixir/lib/module.ex
- https://github.com/elixir-lang/elixir/blob/v1.2.3/lib/elixir/lib/behaviour.ex#L1
- Behaviorは、Elixir 1.2.3 からdepricatedになった。
自身で定義したBehaviourに関して、以下のように @callback で定義したものを、 @behaviour で読み込んで使うという用途で使われます。ここで、読み込んだ先で @callback しているものを def で定義していない場合、 warning が表示されます。
例えば、以下の MyModule や MyGenServer の直前のコメント箇所のような。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule ModuleExample do | |
| @type opts :: tuple | atom | integer | float | [opts] | |
| @callback my_behaviour(opts) :: :ok | :error | |
| # deprecatedだが、 `use Behaviour` と `defcallback` を使うことができる | |
| @callback init(opts) :: :ok | :error | |
| @callback call() :: :ok | :error | |
| end | |
| # sample.exs:13: warning: undefined behaviour function call/0 (for behaviour ModuleExample) | |
| # sample.exs:13: warning: undefined behaviour function init/0 (for behaviour ModuleExample) | |
| defmodule MyModule do | |
| @behaviour ModuleExample | |
| def my_behaviour(:ok), do: :ok | |
| def my_behaviour(:error), do: :error | |
| def my_behaviour(other), do: IO.inspect(other); :ok | |
| end | |
| # sample.exs:27: warning: undefined behaviour function code_change/3 (for behaviour :gen_server) | |
| # sample.exs:27: warning: undefined behaviour function handle_call/3 (for behaviour :gen_server) | |
| # sample.exs:27: warning: undefined behaviour function handle_cast/2 (for behaviour :gen_server) | |
| # sample.exs:27: warning: undefined behaviour function handle_info/2 (for behaviour :gen_server) | |
| # sample.exs:27: warning: undefined behaviour function init/1 (for behaviour :gen_server) | |
| # sample.exs:27: warning: undefined behaviour function terminate/2 (for behaviour :gen_server) | |
| defmodule MyGenServer do | |
| @behaviour :gen_server | |
| end |
これが、例えば、Plugだとこのリンク先 のように定義されていて、こんな感じでcallbackが用意されています。
defmodule MyPlug do @behaviour Plug def init(opts), do: opts def call(conn, _opts), do: conn end
この他にも、 Plug.Builder や Plug.Parsers なんかでも使われています。
他に、
https://github.com/elixir-lang/elixir/blob/v1.2/lib/elixir/lib/module.ex
を見てみるといくつかのattributesが存在することもわかります。これらは、以下の preprocess_attribute/2、 postprocess_attribute\2 で定義されている通りです。
ここによると以下が使われているそうな。その詳細はmoduleのドキュメントを参照ください。
@on_load
@behaviour
@file
@before_compile
@after_compile
@on_definition
@type
@typep
@export_type
@opaque
@callback
@macrocallback@doc
@typedoc
@moduledoc
なるほどね。