Interfaces are like classes, but they don't include any implementation: all interface members are abstract. A class implements an interface by providing an implementation for all the interface members, and by telling the relationship using an implements declaration:
interface Closeable def close() as void end class Resource implements Closeable ... def close() as void -- implementation of close end end
Interfaces may have method and accessor members. The syntax resembles class members, but there is no method body or end.
Note: The interfaces we discuss here are all explicit interfaces. Dynamically-typed code may also use implicit interfaces as explained in Introduction to Alore.
A class may inherit only one class, but it can implement any number of interfaces. Alore supports multiple interface inheritance and single implementation inheritance. This tends to work well in practice. Multiple implementation inheritance is complex and plagued with problems such as diamond inheritance, whereas interface inheritance is mostly immune to these issues.
If a class implements multiple interfaces, separate the interface names by commas:
class A implements I1, I2, ... ... end
If a class explicitly inherits another class and also implements some interfaces, give the superclass before the interfaces (here B is the inherited class):
class A is B implements I1, I2, ... ... end
The Alore standard library defines several interfaces, some of which are commonly used in programs. Here we describe the interfaces std::Iterable, std::Iterator and std::Sequence.
The definition of Iterable is as follows:
interface Iterable<T> def iterator() as Iterator<T> end
The interface is generic. An Iterable object supports iteration, and the iteration produces objects of type T. Here is the definition of Iterator:
interface Iterator<T> def hasNext() as Boolean def next() as T end
The Sequence interface is implemented by classes which support indexing with  using integers, such as Array and Str. Sequence is defined like this:
interface Sequence<T> def _get(i as Int) as T -- Operation sequence[i] def length() as Int end
The object to iterate in a for loop must implement Iterable<T>. The type of the loop variable is inferred from the type variable T of the iterated object. In the example below the iterated object has type Range, and Range implements Iterable<Int>; therefore the type of i will be Int:
for i in 0 to 5 Print(i + 1) end
The above example is equivalent to the following code, with explicit types for clarity:
var iterable = 0 to 5 as Iterable<Int> var iterator = iterable.iterator() as Iterator<Int> while iterator.hasNext() var i = iterator.next() as Int Print(i + 1) end
Note that the type of iterable could equally have been Range.
You can also set an interface to be a supertype of an existing class, directly within the interface definition. Do this with a bind declaration:
class A def length() as Int ... end end interface WithLength bind A -- Set WithLength to be supertype of A def length() as Int end
Now A implements WithLength, so the following is fine:
var l as WithLength l = A() l.length()
The above definitions are equivalent to the following code, where the class declares the implementation:
class A implements WithLength def length() as Int end interface WithLength def length() as Int end
You can also bind interfaces to classes defined in other modules, including standard library classes. Sometimes it is even useful to bind interfaces to such basic types as Int or Str.
Interfaces may not include member variables or constants, but they can define accessors. Classes that implement an interface may use variables or constants to implement the accessors:
interface Accessors def n as Int def n = x as Int end class Variables implements Accessors var n as Int -- Implementation of getter and setter for n end