ビヘ

ビヘイビア の Elixir

1個の演習

ビヘイビアについて

ビヘイビアを使うと、_ビヘイビアモジュール_の中でインターフェース(関数とマクロの集まり)を定義できます。これを後から別々の_コールバックモジュール_で実装できます。インターフェースを共有しているおかげで、これらのコールバックモジュールは互いに置き換えて使うことができます。

Note

「behaviours」はイギリス英語のつづりであることに注意してください。

ビヘイビアを定義する

ビヘイビアを定義するには、新しいモジュールを作成し、必要なインターフェースに含まれる関数の一覧を指定します。各関数は、モジュール属性@callbackを使って定義します。構文は関数の型仕様(@spec)とまったく同じです。指定するのは、関数名、引数の型の一覧、そして取りうる戻り値の型すべてです。

defmodule Countable do
  @callback count(collection :: any) :: pos_integer
end

ビヘイビアを実装する

既存のビヘイビアを自分のモジュールに追加する(コールバックモジュールを作る)には、モジュール属性@behaviourを使います。値には、追加するビヘイビアモジュールの名前を指定します。

次に、そのビヘイビアモジュールが要求する関数(コールバック)をすべて定義します。Elixirに組み込みのAccessやGenServerなど、他の人が作ったビヘイビアを実装する場合は、そのビヘイビアのコールバックの一覧がhexdocs.pmのドキュメントに載っています。

コールバックモジュールは、自分のビヘイビアに含まれる関数だけを実装しなければならないわけではありません。1つのモジュールで複数のビヘイビアを実装することもできます。

どの関数がどのビヘイビア由来なのかを示すには、各関数の前にモジュール属性@implを付けます。値には、そのコールバックを定義しているビヘイビアモジュールの名前を指定します。

defmodule BookCollection do
  @behaviour Countable

  defstruct [:list, :owner]

  @impl Countable
  def count(collection) do
    Enum.count(collection.list)
  end

  def mark_as_read(collection, book) do
    # other function unrelated to the Countable behaviour
  end
end

コールバックのデフォルト実装

ビヘイビアを定義するときは、コールバックのデフォルト実装を用意できます。この実装は、__using__/1マクロのquote式の中に定義します。ビヘイビアモジュールを使う側がデフォルト実装を上書きできるようにするには、関数の実装のあとでdefoverridable/1マクロを呼びます。このマクロは、関数名をキー、関数のアリティを値とするキーワードリストを受け取ります。

defmodule Countable do
  @callback count(collection :: any) :: pos_integer

  defmacro __using__(_) do
    quote do
      @behaviour Countable
      def count(collection), do: Enum.count(collection)
      defoverridable count: 1
    end
  end
end

__using__/1の中で関数を定義するのは、コールバックのデフォルト実装を定義する以外の目的ではおすすめしません。ただし、別のモジュールで関数を定義して、それを__using__/1マクロの中でインポートすることはいつでもできます。

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

ビヘイビアを学習する