プロトコル (Protocol) と ビヘイビア (Behaviour) はどちらも多態性を実現する仕組みだが、目的が異なる。
プロトコル — データ型に基づくディスパッチ
異なるデータ型に対して同じ関数を呼び出せるようにする仕組み。外部から型に機能を追加できる。いわゆるアドホック多態性。
elixirdefprotocol Stringify do
def to_str(data)
end
defimpl Stringify, for: Integer do
def to_str(n), do: "整数: #{n}"
end
defimpl Stringify, for: BitString do
def to_str(s), do: "文字列: #{s}"
end
Stringify.to_str(42) #=> "整数: 42"
Stringify.to_str("hello") #=> "文字列: hello"ポイント
渡されたデータの型によって呼ばれる実装が変わる。
ビヘイビア — モジュールが満たすべき契約(インターフェース)
モジュールが特定の関数を実装することを強制する仕組み。OOPのインターフェース/抽象クラスに近い。
elixirdefmodule Parser do
@callback parse(String.t()) :: {:ok, any()} | {:error, String.t()}
end
defmodule JsonParser do
@behaviour Parser
@impl true
def parse(str), do: Jason.decode(str)
end
defmodule CsvParser do
@behaviour Parser
@impl true
def parse(str), do: {:ok, String.split(str, ",")}
endポイント
どのモジュールを使うかは呼び出し側が明示的に選ぶ。コンパイル時に未実装の関数があれば警告が出る。
まとめ
| プロトコル | ビヘイビア | |
|---|---|---|
| ディスパッチ基準 | データの型(自動) | モジュール(明示的) |
| 類似概念 | Haskellの型クラス, Rustのtrait | Java/Goのインターフェース |
| 主な用途 | 異なる型への統一的な操作 | モジュールの契約・差し替え可能な実装 |
| チェック時期 | 実行時 | コンパイル時(警告) |
TypeScriptと比べる
プロトコル ≒ 引数の型によるオーバーロード/分岐
// Elixirのプロトコルに相当するイメージ
function toStr(data: number): string;
function toStr(data: string): string;
function toStr(data: unknown): string {
if (typeof data === "number") return `整数: ${data}`;
if (typeof data === "string") return `文字列: ${data}`;
throw new Error("未対応の型");
}
toStr(42); // "整数: 42"
toStr("hello"); // "文字列: hello"渡したデータの型で挙動が変わる。しかもElixirでは後から新しい型への実装を追加できる(オープン)。
ビヘイビア ≒ インターフェース (interface)
// Elixirのビヘイビアに相当
interface Parser {
parse(str: string): { ok: boolean; data?: any; error?: string };
}
class JsonParser implements Parser {
parse(str: string) {
return { ok: true, data: JSON.parse(str) };
}
}
class CsvParser implements Parser {
parse(str: string) {
return { ok: true, data: str.split(",") };
}
}
// どの実装を使うかは呼び出し側が選ぶ
function run(parser: Parser, input: string) {
return parser.parse(input);
}モジュール(クラス)が契約を満たしているかをコンパイル時にチェックする仕組み。
| Elixir | TypeScript相当 |
|---|---|
| プロトコル | 引数の型で分岐するオーバーロード(+後から拡張可能) |
| ビヘイビア | interface + implements |