Behaviours

Get a brief overview of behaviours in Elixir.

When we wrote our OTP server, we wrote a module that started with the following code:

defmodule Sequence.Server do 
  use GenServer
  ...

In this chapter, we’ll explore what lines such as use GenServer actually do and how we can write modules that extend the capabilities of other modules that use them.

An Elixir behaviour is nothing more than a list of functions. A module that declares that it implements a particular behaviour must implement all of the associated functions. If it doesn’t, Elixir generates a compilation warning. We can think of a behaviour definition as being like an abstract base class in some object-oriented languages.

A behaviour is therefore a little like an interface in Java. A module uses it to declare that it implements a particular interface. For example, an OTP GenServer should implement a standard set of callbacks (handle_call, handle_cast, and so on). By declaring that our module implements that behaviour, we let the compiler validate that we have actually supplied the necessary interface. This reduces the chance of an unexpected runtime error.

Defining behaviours

We define a behaviour with @callback definitions.

For example, the mix utility can fetch dependencies from various source code control systems. Out of the box, it supports Git and the local filesystem. However, the interface to the source code control system (which mix abbreviates internally as SCM) is defined using a behaviour, allowing new version control systems to be added cleanly. The behaviour is defined in the module Mix.SCM:

Get hands-on with 1200+ tech skills courses.