Generic inheritance and generic interfaces

Note: This section is a stub.

This section explains how to inherit from a generic type and how to implement a generic interface. We illustrate these by expanding the Stack class defined in section Defining a generic type.

Implementing a generic interface

Here is a modified version of the stack example that implements the Iterable interface (differences are highlighted):

class Stack<T> implements Iterable<T>
  private var array = [] as Array<T>

  def create() as void
  end

  def iterator() as Iterator<T>
    return self.array.iterator()
  end

  def isEmpty() as Boolean
    return self.array == []
  end

  def push(o as T)
    self.array.append(o)
  end

  def pop() as T
    self.array.removeAt(-1)
  end
end

Inheriting from a generic class

We can define subclasses of a generic class such as Stack:

class IntStack is Stack<Int>
end

class ArrayStack<S> is Stack<Array<S>>
end

The IntStack class is a non-generic class that inherits Stack; it fixes the type variable T to Int. IntStack is compatible with Stack<Int>. ArrayStack also inherits Stack, but it is generic like Stack. ArrayStack<Int> is compatible with Stack<Array<Int>> (and similarly for other values of type variable S).

Note that a generic subclass may not define additional type variables not present in the superclass (unless the superclass is Object). Each type variable in a subclass must be mapped to a superclass type variable. The following class is not valid, since the subclass defines two type variable while the superclass only has one:

class TupleStack<T1, T2> is Stack<(T1, T2)>
end

This restriction does not apply to interface inheritance.

Generic inheritance and mixed typing

You can also inherit a dynamically-typed class from a generic class:

class DynStack is Stack
  def length()
    return Array(iterator()).length()
  end
end

In this case the type variable T of Stack defaults to dynamic for instances of DynStack.