Search code examples
javainterfaceerlangdialyzer

Emulating Interfaces using Behaviours with Dialyzer in Erlang


I want a Java interface equivalent in Erlang. How can I provide a -spec contract for the dialyzer that will allow me to get the as close as possible to functionality provided in Java?

Lets say I want something equivalent to this:

//Filename: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

//Filename: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

//Filename: Hockey.java
public interface Hockey extends Sports
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}

Solution

  • You can implement this with -callback attributes:

    %% Filename: sport.erl
    -module(sport).
    
    -callback setHomeTeam(Name :: string()) -> ok.
    -callback setVisitingTeam(Name :: string()) -> ok.
    

    Then whenever you want to provide this interface:

    -behavior(sport).
    

    I cannot however currently think of a way to do inheritance between behaviours. You can emulate it with included .hrl files that contain the relevant -behaviour attributes, instead of specifying them verbatim but this feels dirty.

    Dialyzer will check that the callback satisfy the specified -specs if the behaviour modules are analyzed together with the modules that use them or are already in the PLT.