Tracce
/
Elixir
Elixir
/
Programma
/
Behaviours
Be

Behaviours in Elixir

1 esercizio

Informazioni su Behaviours

I behaviour ci permettono di definire delle interfacce (insiemi di funzioni e macro) in un modulo di behaviour che potrà essere implementato in seguito da diversi moduli di callback. Grazie all'interfaccia condivisa, questi moduli di callback possono essere usati in modo intercambiabile.

Note

Nota l'ortografia britannica di «behaviours».

Definire i behaviour

Per definire un behaviour, dobbiamo creare un nuovo modulo e specificare un elenco di funzioni che fanno parte dell'interfaccia desiderata. Ogni funzione va definita usando l'attributo di modulo @callback. La sintassi è identica a quella di una typespec di funzione (@spec). Dobbiamo specificare il nome di una funzione, un elenco di tipi di argomento e tutti i possibili tipi restituiti.

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

Implementare i behaviour

Per aggiungere un behaviour esistente al nostro modulo (creando così un modulo di callback) usiamo l'attributo di modulo @behaviour. Il suo valore deve essere il nome del modulo di behaviour che stiamo aggiungendo.

Poi dobbiamo definire tutte le funzioni (callback) richieste da quel modulo di behaviour. Se stiamo implementando il behaviour di qualcun altro, come i behaviour integrati di Elixir Access o GenServer, troveremo l'elenco di tutti i callback del behaviour nella documentazione su hexdocs.pm.

Un modulo di callback non è limitato a implementare solo le funzioni che fanno parte del suo behaviour. Un singolo modulo può anche implementare più behaviour.

Per indicare da quale behaviour proviene ogni funzione, dobbiamo usare l'attributo di modulo @impl prima di ciascuna funzione. Il suo valore deve essere il nome del modulo di behaviour che definisce questo callback.

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

Implementazioni predefinite dei callback

Quando si definisce un behaviour, è possibile fornire un'implementazione predefinita di un callback. Questa implementazione va definita nell'espressione quotata della macro __using__/1. Per permettere a chi usa il modulo di behaviour di sovrascrivere l'implementazione predefinita, chiama la macro defoverridable/1 dopo l'implementazione della funzione. Accetta una keyword list con i nomi delle funzioni come chiavi e la loro arietà come valori.

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

Tieni presente che definire funzioni dentro __using__/1 è sconsigliato per qualsiasi scopo diverso dal definire implementazioni predefinite dei callback, ma puoi sempre definire le funzioni in un altro modulo e importarle nella macro __using__/1.

Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda

Impara Behaviours