<< | Contents | Dependent Types >>
Classes, Refinement and Composition
Types of Classes (cls.types)
(cls.types.1) Caesar supports two types of classes Java classes and Caesar classes.
Def: Java classes are conventional classes, complying to
JLS.
Def: Caesar classes are extended Java classes, which provide additional Caesar specific features and have slightly different semantics, which will be defined further in this specification.
(cls.types.2) Java classes are declared with keyword
class
(cls.types.3) Ceasar classes are declared with keyword
cclass
.
Nesting (cls.nest)
(cls.nest.1) Caesar class can be defined on top level or be nested within another Caesar class.
Def: Nested Caesar classes are
virtual classes.
Def: A Caesar class having nested classes is also called
collaboration. The directly enclosing class of a virtual class is the collaboration of the class.
(cls.nest.2) The name of a nested class must be unique within the collaboration.
(cls.nest.3) Unlimited levels of nesting are allowed.
Restrictions
(cls.nest.4) A Java class cannot be nested within a Caesar class.
(cls.nest.5) A Caesar class cannot be nested within a Java class.
(cls.nest.6) Interfaces cannot be nested within a Caesar class.
Example: In List.1
Graph
is a top level Caesar class. Classes
Node
and
Edge
are nested within
Graph
, so they are virtual classes of
Graph
, and
Graph
is the collaboration of
Edge
and
Node
.
Listing 1.
package examples.graph;
public cclass Graph {
public cclass Node {
...
}
public cclass Edge {
...
}
}
(cls.nest.7) Nested Caesar class can also be defined outside the collaboration in a separate file. At the beginning of such file there must be a
cclass
declaration with the fully qualified name of the collaboration. This declaration replaces
package
declaration for the file.
Example: In List.2 class
UndirectedEdge
is a virtual class of
Graph
, but defined in a separate file. Therefore there is a
cclass
declaration with fully qualified name of
Graph
at the beginning of the file instead of
package
declaration.
Listing 2.
/* File UndirectedEdge.java */
cclass examples.graph.Graph;
cclass UndirectedEdge extends Edge {
...
}
Outer Object (cls.outer)
(cls.outer.1) Instance of a nested class always contains a reference to an instance of the directly enclosing class.
Def: The instance of the enclosing class is called
outer object.
(cls.outer.2) Outer object can be accessed through qualified
this
in a similar way as in Java.
(cls.outer.3) Outer access can also be determined implicitly for method calls.
(cls.outer.4) Outer access from an instance of a top level Caesar class is not allowed.
(cls.outer.5) Only the public members of the outer object can be accessed.
(cls.outer.6) Outer reference cannot be changed after the instantiation of the object.
Example: In List.3 any instance of class
Inner
has a reference to an instance of class
Outer
and can call its public methods.
It can be determined implicitly that the call of method
methB()
is a call on outer object.
Method
methA()
also exists in class
Inner
, so outer must be referenced explicitly using
this
, qualified with
Outer
.
Listing 3.
public cclass Outer {
public void methA() { }
public void methB() { }
public cclass Inner {
public void methA() { }
public void test() {
methA(); /* call on this */
methB(); /* call on outer */
Outer.this.methA(); /* call on outer */
}
}
}
Class Inheritance (inh.types)
(inh.types.1) There are two types of inheritance between Caesar classes - generalization and overriding
Def: Generalization (specialization) – logical, explicitly defined inheritance relationship between Caesar classes.
Def: Overriding (refinement) – an overriding class implicitly inherits from its overridden versions.
Def: The inherited class is called
superclass, the inheriting class is called
subclass. So superclasses of a class are its generalizations and the overridden classes. The subclasses of a class are its specializations and overriding classes.
(inh.types.2) Caesar class can implement any number of interfaces. Implemented interfaces are listed in
implements
clause and separated by commas.
Different types of classes cannot be mixed in extends declarations:
- (inh.types.3) A Java class cannot extend a Caesar class.
- (inh.types.4) A Caesar class cannot extend a Java class.
Class Generalization (inh.gener)
(inh.gener.1) A Caesar class can be declared as a specialization of any number of Caesar classes. The generalizations of the class are listed in
extends
clause and separated by mixin operator
“&”
.
(inh.gener.2) A Caesar class inherits all members and nested classes from its generalizations.
(inh.gener.3) Only the classes of the same collaboration can stand in generalization relationship.
(inh.gener.4) Top level Caesar class can inherit only from other top level Caesar classes.
(inh.gener.5) Cross collaboration generalization relationships are disallowed.
(inh.gener.6) Generalization relationships between Caesar classes with different nesting level are disallowed.
Example: In the List.4 there are generalization relationships on the top level as well as inside the collaborations.
CompositeShapes
has two generalizations:
Shapes
and
CompositePattern
Component
is generalization of
Composite
in the collaboration
CompositePattern
.
Shape
is generalization of
Circle
in the collaboration
Shapes
.
Collaboration
CompositeShapes
inherits all generalization relationships from
CompositePattern
and
Shapes
. It also defines new generalization relationships.
Composite
and
Shape
are generalizations of
CompositeShape
.
Shape
is also defined as specialization of
Component
.
Listing 4.
public cclass CompositePattern {
public cclass Component {
...
}
public cclass Composite extends Component {
...
}
}
public cclass Shapes {
public cclass Shape {
...
}
public cclass Circle extends Shape {
...
}
}
public cclass CompositeShapes extends Shapes & CompositePattern {
public cclass CompositeShape extends Composite & Shape {
...
}
public cclass Shape extends Component {
...
}
}
The complete generalization hierarchy within
CompositeShapes
is:
Overriding Classes (inh.overr)
(inh.overr.1) Collaboration can define a nested virtual class with the same name as one of the inherited virtual classes. In this case the newly defined virtual class overrides the inherited class in the context of the collaboration. The overriding class is known as a refinement or a further-binding.
(inh.overr.2) Collaboration can inherit multiple virtual classes with the same name from its superclasses. All these classes are overridden by a new virtual class with the same name. If such class does not exist, it is implicitly created.
(inh.overr.3) Overriding class inherits all members, nested virtual classes from all overridden classes.
(inh.overr.4) Overriding class inherits all generalizations of the overridden classes.
(inh.overr.5) The inherited generalizations need not to be repeated in the overriding class.
(inh.overr.6) Overriding class can introduce new generalizations by listing them in the
extends
clause.
Example: In the List.4
Shape
of
CompositeShapes
overrides the
Shape
class inherited from collaboration
Shapes
. So
CompositeShapes.Shape
is overriding class of
Shapes.Shape
.
CompositeShapes.Circle
is overriding class of
Shapes.Circle
. This class is not overridden explictly, but it still will be different, because its generalization
Shape
has been overriden.
Mixin Linearization
A class may inherit a method with the same name from multiple super classes.
CaesarJ? resolves such conflicts automatically using mixin linearization process.
Def: All Caesar class declarations are considered as
mixins, i.e. classes with replaceable superclass, so that they can be flexibly ordered to various linear inheritance sequences. This ordering process is called
mixin linearization.
Linearization Effect (inh.resol)
For each Caesar class C, all inherited class declarations (mixins) and its own declaration are ordered into a sequence [M1, M2, … Mn] with following effect:
(inh.resol.1) If there are several mixins, which define a class member with the same name, C inherits the member definition from the leftmost mixin.
(inh.resol.2) The lookup for a super method call in class C starts from M2 and continues along the sequence until the method with required name is found.
Linearization Rules (inh.linear)
Mixin list of class C is defined according following rules:
- (inh.linear.1) All inherited mixins of class C appear in the mixin list.
- (inh.linear.2) The same mixin is included only once in the list.
- (inh.linear.3) Linearization must preserve generalization links, i.e. if class A is a generalization of class B in the collaboration of class C, all mixins of A are positioned after all mixins of B.
- (inh.linear.4) Linearization must preserve the class ordering in extends clause, i.e. if in the extends clause of any of the mixins, inherited by class C, generalization A is listed after generalization B, then all mixins of A must also be ordered after all mixins of B.
- (inh.linear.5) Linearization must preserve overriding sequence, i.e. if mixin A1 overrides mixin A2, A1 is positioned before A2.
(inh.linear.6) If no mixin sequence is possible, which complies to the above rules, the rule
(inh.linear.4) is ignored.
(inh.linear.7) If the above rules to not restrict order between mixins Mi and Mj, their ordering is not determined by the specification and left free for compiler implementation.
Example: In the List.4 the mixins of
CompositeShapes.Circle
are all its inherited class declarations, i.e. the declarations of
Circle
and the declarations all its generalizations:
Shape
and
Component
. So, the mixins of
CompositeShapes.Circle
are:
Shapes.Circle
Shapes.Shape
Composite.Component
CompositeShapes.Shape
According
inh.linear.3 the mixin order must follow generalization hierarchy, so the mixins of
Circle
must be followed by mixins of
Shape
, and the mixins of
Shape
must be followed by mixins of
Component
:
[
Shapes.Circle
,
Shapes.Shape
,
CompositeShapes.Shape
,
CompositePattern.Component
]
This order is still not correct.
CompositeShapes.Shape
overrides
Shapes.Shape
, so according
inh.linear.5 CompositeShapes.Shape
must be placed before
Shapes.Shape
. So the correct linearization of
CompositeShapes.Circle
mixins is:
[
Shapes.Circle
,
CompositeShapes.Shape
,
Shapes.Shape
,
CompositePattern.Component
]
The mixin list of
CompositeShapes.CompositeShape
is
[
CompositeShapes.CompositeShape
,
CompositePattern.Composite
,
CompositeShapes.Shape
,
Shapes.Shape
,
CompositePattern.Component
]
This linearization does not contradict generalization and overriding relationships. There is no relationship is define between
Shape
and
Composite
, but
Composite
still must be positioned before
Shape
, because these classes appear in this order in the
extends
clause of
CompositeShapes.CompositeShape
(see
inh.linear.4).
Constructors (cls.constr)
(cls.constr.1) Caesar class may have only the default constructor - the constructor without parameters.
(cls.constr.2) The constructors of all superclasses are automatically called in the order defined by mixin linearization rules.
Visibility (cls.visib)
(cls.visib.1) A Caesar class must have public visibility
(cls.visib.2) Caesar class methods may have public, protected or private visibility
(cls.visib.3) Non-static class fields may have protected or private visibility
(cls.visib.4) Static class fields may have public, protected or private visibility
(cls.visib.5) Class members with private visibility are visible only within the same class declaration, i.e. they are not visible in the overriding classes.
(cls.visib.6) Class members with protected visibility are visible in all subclasses of the class.
Instantiation (cls.inst)
(cls.inst.1) A top level Caesar class is instantiated using simple new operator.
(cls.inst.2) A virtual class can be instantiated only in the context of an instance of its collaboration. The qualified
new
operator is used.
(cls.inst.3) Expression
exp.new cls()
, where
exp
is any expression returning collaboration object, has following semantics:
- Virtual class
cls
, declared within the run-time class of exp
, is instantiated.
- Class
cls
must be declared in the statically known class of exp
.
- The object, returned by
exp
, becomes the outer object of the new instance of cls
.
(cls.inst.4) Unqualified instantiation of a virtual class
new cls()
is assumed as instantiation in the context of
this
instance or some outer of
this
, which contains class
cls
.
Example: In List.5
Node
is a virtual class, so it cannot be instantiated directly. It can be instatiated only in the context of a
Graph
object.
Expression
new Node()
inside
Graph
class is assumed as instantiation in the context of
this
instance, i.e.
this.new Node()
.
Expression
new Node()
inside
Edge
class is assumed as instantiation in the context of the enclosing graph instance, i.e.
Graph.this.new Node()
.
Listing 5.
public cclass Graph {
public Node defaultNode() {
return new Node(); /* OK */
}
public cclass Node {
...
}
public cclass Edge {
Node n1, n2;
public void disconnectEnd() {
n2 = new Node(); /* OK */
}
}
}
public class Test {
public void test() {
Graph.Node n = new Graph.Node(); /* error! */
Graph g = new Graph(); /* OK */
g.Node n = g.new Node(); /* OK */
}
}
Abstract Classes (cls.abstr)
(cls.abstr.1) Caesar classes can be declared as abstract using
abstract
modifier.
(cls.abstr.2) An implicitly inherited class is abstract if and only if all the classes, which it overrides, are abstract.
(cls.abstr.3) A concrete virtual class cannot be overriden by an abstract class. (Nevertheless it can still have abstract specializations)
(cls.abstr.4) Abstract collaborations can contain concrete virtual classes, as well as concrete collaborations can contain abstract virtual classes.
(cls.abstr.5) A Caesar class can contain abstract methods if and only if it is abstract or some of its enclosing collaborations is abstract.
(cls.abstr.6) A top level abstract Caesar class cannot be instantiated.
(cls.abstr.7) Virtual class instantiation of form
exp.new cls
is allowed if and only if
cls
is not abstract in the statically known type of
exp
.
<< | Contents | Dependent Types >>