Behaviours

Behaviours define a contract (set of callbacks) a module must implement — module-level polymorphism.

Behaviours define a contract (set of callbacks) a module must implement — module-level polymorphism.

@impl true makes the compiler warn if a function isn't a callback (or a callback is missing).

Protocols vs behaviours: protocols dispatch on the *data*; behaviours define what a *module* must provide (GenServer, Supervisor, Plug, Ecto adapters are behaviours).

defmodule Parser do
  @callback parse(String.t()) :: {:ok, term()} | {:error, String.t()}
  @callback extensions() :: [String.t()]
  @optional_callbacks extensions: 0

  def parse_with(module, input), do: module.parse(input)
end

defmodule JSONParser do
  @behaviour Parser

  @impl Parser
  def parse(str), do: {:ok, str}

  @impl Parser
  def extensions, do: [".json"]
end

Parser.parse_with(JSONParser, "{}")