Skip to content

Commit 3b5bb5c

Browse files
committed
Add a "Behaviours" page to the documentation (#4782)
1 parent f79ebda commit 3b5bb5c

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ docs: compile ../ex_doc/bin/ex_doc docs_elixir docs_eex docs_mix docs_iex docs_e
137137
docs_elixir: compile ../ex_doc/bin/ex_doc
138138
@ echo "==> ex_doc (elixir)"
139139
$(Q) rm -rf doc/elixir
140-
$(call COMPILE_DOCS,Elixir,elixir,Kernel,-e "lib/elixir/pages/Naming Conventions.md" -e "lib/elixir/pages/Typespecs.md" -e "lib/elixir/pages/Writing Documentation.md")
140+
$(call COMPILE_DOCS,Elixir,elixir,Kernel,-e "lib/elixir/pages/Behaviours.md" -e "lib/elixir/pages/Naming Conventions.md" -e "lib/elixir/pages/Typespecs.md" -e "lib/elixir/pages/Writing Documentation.md")
141141

142142
docs_eex: compile ../ex_doc/bin/ex_doc
143143
@ echo "==> ex_doc (eex)"

lib/elixir/pages/Behaviours.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Behaviours
2+
3+
Behaviours in Elixir (and Erlang) are a way to separate and abstract the generic part of a component (which becomes the *behaviour module*) from the specific part (which becomes the *callback module*).
4+
5+
A behaviour module defines a set of functions and macros (referred to as *callbacks*) that callback modules implementing that behaviour must export. This "interface" identifies the specific part of the component. For example, the `GenServer` behaviour and functions abstract away all the message-passing (sending and receiving) and error reporting that a "server" process will likely want to implement from the specific parts such as the actions that this server process has to perform.
6+
7+
If a callback module that implements a given behaviour doesn't export all the functions and macros defined by that behaviour, the user will be notified through warnings during the compilation process (no errors will happen).
8+
9+
Elixir's standard library contains a few frequently used behaviours such as `GenServer`, `Supervisor`, and `Application`.
10+
11+
## Defining a behaviour
12+
13+
A behaviour is always backed by a module (which is how the behaviour will be identified): the module where callbacks are defined. To define a behaviour module, it's enough to define one or more callbacks in that module. To define callbacks, the `@callback` and `@macrocallback` module attributes can be used (for function callbacks and macro callbacks respectively).
14+
15+
defmodule MyBehaviour do
16+
@callback my_fun(arg :: any) :: any
17+
@macrocallback my_macro(arg :: any) :: Macro.t
18+
end
19+
20+
As seen in the example above, defining a callback is a matter of defining a specification for that callback, made of:
21+
22+
* the callback name (`my_fun` or `my_macro` in the example)
23+
* the arguments that the callback must accept (`arg :: any` in the example)
24+
* the *expected* type of the callback return value
25+
26+
For more information on typespecs, consult the ["Typespecs"](typespecs.html) page in the Elixir documentation. As mentioned in this page, type specification are only annotations used by documentation and tools, so defining such specifications for behaviours serves mostly for such purposes.
27+
28+
### Optional callbacks
29+
30+
Optional callbacks are callbacks that callback modules may implement if they want to, but are not required to. Usually, behaviour modules provide a default implementation for such callbacks in case the callback module does not implement them. Optional callbacks can be defined through the `@optional_callbacks` module attribute, which has to be a list of `{function_or_macro_name, arity}` tuples. For example:
31+
32+
defmodule MyBehaviour do
33+
@callback vital_fun() :: any
34+
@callback non_vital_fun() :: any
35+
@macrocallback non_vital_macro(arg :: any) :: Macro.t
36+
@optional_callbacks non_vital_fun: 0, non_vital_macro: 1
37+
end
38+
39+
One example of optional callback in Elixir's standard library is `c:GenServer.format_status/2`.
40+
41+
## Implementing behaviours
42+
43+
To specify that a module implements a given behaviour, the `@behaviour` attribute must be used:
44+
45+
defmodule MyBehaviour do
46+
@callback my_fun(arg :: any) :: any
47+
end
48+
49+
defmodule MyCallbackModule do
50+
@behaviour MyBehaviour
51+
def my_fun(arg), do: arg
52+
end

lib/elixir/pages/Typespecs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ Types can be parameterized by defining variables as parameters; these variables
148148
@callback function_name(type1, type2) :: return_type
149149
@macrocallback macro_name(type1, type2) :: Macro.t
150150

151-
Callbacks are used to define the callbacks functions of behaviours (see `Behaviour`).
151+
Callbacks are used to define the callbacks functions of behaviours (see the ["Behaviours"](behaviours.html) page in the documentation for more information on behaviours).
152152

153153
Guards can be used to restrict type variables given as arguments to the function.
154154

0 commit comments

Comments
 (0)