@head @title Inheritance and subtyping
If class X extends (inherits from) class Y, you can use a value with type X (the subtype) whenever a value of type Y (the supertype) is expected. For example, io::File inherits from io::Stream. Therefore, the following code is valid: @example var s as Stream var f = File('data.txt') as File s = f @end
As s has type Stream, we can only access members defined in Stream by using s. For example, seek is defined in File but not in Stream: @example f.seek(2) -- Ok s.seek(2) -- Error: member "seek" not defined in Stream @end @h2 The Object type
The Object is the top of the Alore class hierarchy: every other class is a subclass of Object, either directly or via a superclass. Thus any Alore value can be stored in a variable with the Object type: @example var o as Object o = 1 -- Ok o = 'x' -- Ok @end
However, values with the Object type only support a few interesting operations. You can use casts, discussed later in Section @href{Casts}, to convert an Object value to a more specific type. @h2 Overriding methods
If a method overrides a superclass method, the signature of the method must be compatible with the superclass method. In the simple case the signature is identical: @example import io class Super def open(path as Str) as Stream return File(path) end end class Sub is Super def open(path as Str) as Stream -- Ok: identical signature return File(path + '.ext') end end @end
The overriding method may define additional optional arguments compared to the original method signature. Intuitively, the overriding method is still compatible because it can be called with either the original signature or with the additional arguments. Here is an example: @example class Super def f(a as Int) ... end def g() as void ... end end class Sub is Super def foo(a as Int, b = '' as Str) -- Ok, since b is optional ... end def g(*args as Int) -- Ok, since args is a varargs argument ... end end @end
In addition, the argument types in the subclass may be supertypes of the corresponding supertype method argument (contravariance). Similarly, the return type may be a subtype of the return type of the supertype method (covariance): @example class Sub is Super def open(path as Object) as File -- Ok: contravariant argument type, ... -- covariant return value type end end @end
The above example is valid, since Object (type of path) is a supertype of Str, and the return type File is a subtype of Stream.
We will discuss how the type dynamic affects overriding later in Section @href{The dynamic type and mixed typing}. @h2 Overriding member variables and accessors
A subclass may override member variables and accessors defined in a superclass using accessors. In this case the type in the subclass must be equivalent to the superclass type. This example illustrates it: @example class Super var i as Int var o as Object end class Sub is Super def i as Int -- Ok, same type as in superclass ... end def o as Str -- Error: Str incompatible with Object ... end end @end