| Methods | categories Methods and Types Types |
Polymorphism |
CLAIRE uses an extended type system that is built on top of the set of classes. Like a class, a type denotes a set of objects, but it can be much more precise than a class. Since methods are attached to types (by their signature), this allows attaching methods to complex sets of objects.
Definition : A (data) type is an expression that represents a set of objects. Types offer a finer-granularity partition of the object world than classes. They are used to describe objects (range of slots), variables and methods (through their signatures). An object that belongs to a type will always belong to the set represented by the type. |
Any class (even parameterized) is a type. A parameterized class type is obtained by filtering a subset of the class parameters with other types to which the parameters must belong. For instance, we saw previously that complex[im:{0.0}] is a parametrized type that represent the real number subset of the complex number class. This also applies to typed lists or sets which use the of parameter. For instance, list[of:{integer}] is the set of list whose of parameter is precisely integer. Since these are common patterns, CLAIRE offers two shortcuts for parameterized type expressions. First, it accepts the expression C[p = v] as a shortcut for C[p:{v}]. Second, it accepts the expression C<X> as a shortcut for C[of = X]. This applies to any class with a type-valued parameter named of; Thus, stack<integer> is the set of stacks whose parameter "of" is exactly integer, whereas stack[of:subtype[integer]] is the set of stacks whose parameter (a type) is a subset of integer.
Finite constant sets of objects can also be used as types. For example, {john, jack, mary} and {1,4,9} are types. Intervals can be used as types; the only kind of intervals supported by CLAIRE 3.0 is integer intervals. Types may also formed using the two intersection (^) and union (U) operations. For example, integer U float denotes the set of numbers and (1 .. 100) ^ (-2 .. 5) denotes the intersection of both integer intervals, i.e. (1 .. 5).
Subtypes are also as type expressions. First, because types are also objects, CLAIRE introduces subtype[t] to represent the set of all type expressions that are included in t. This type can be intersected with any other type, but there are two cases which are more useful than other, namely subtypes of the list and set classes. Thus, CLAIRE uses set[t] as a shortcut for set ^ subtype[t] and list[t] as a shortcut for list ^ subtype[t]. Because of the semantics of lists, one may see that list[t] is the union of two kinds of lists :
Classes are sorted with the inheritance order. This order can be extended to types with the same intuitive meaning that a type t1 is a subtype of a type t2 if the set represented by t1 is a subset of that represented by t2. The relation "t1 is a subtype of a type t2" is noted t1 <= t2. This order supports the introduction of the " subtype " constructor: subtype[t] is the type of all types that are less than t.
| categories | Types | normal dispatch | operation | Kernel method |
(x % y) returns (x E y) for any entity x and any abstract set y. An abstract set is an object that represents a set, which is a type or a list.
| categories | Types | normal dispatch | operation | Kernel method |
x .. y returns the interval interval (x .. y).
| categories | Types | normal dispatch | operation | Kernel method |
The order on types is the inclusion: (x <= y) returns true if all members of type x are members of type y.
| categories | Types | normal dispatch | operation | Core method |
returns true if x and y denote the same type. For example =type?(boolean, {true, false}) returns true because defined(boolean) was declared after the two instances true and false were created, so the system knows that no other instances of boolean may ever be created in the future. This equality is stronger than set equality in the sense that the system answers true if it knows that the answer will hold everafter.
| categories | Types | normal dispatch | Kernel method |
final(c) forbids the user to create any subclass of the class c. If c is a constant class, this is taken as a "diet" compiling directive.
| categories | Types | normal dispatch | Core method |
finite?(self) returns true if the type self represents a finite set. Set iteration (with the for loop) can only be done over finite sets.
| categories | Types | normal dispatch | operation | Core method |
inherit?(self, ens) returns (self % ancestors(ens)).
| categories | Types | normal dispatch | Core method |
member(x) returns the type of all instances of type x, assuming that x is a CLAIRE type which contains objects y such that other objects z can belong to. If this is the case, member(x) is a valid type for all such z, otherwise the returned value is the empty set. For instance, if x is list[integer], all instances of x are lists that contain integers, and all members of these lists are integers. Therefore, member(list[integer]) is integer.