Home

Documentation

* Programming Guide * CJDT User Guide * Publications * Tutorial * Language Spec.

Examples

Downloads

Source Code

FAQ

Community Info

About Us

 

 
Search:
 
ST Logo
TUD Logo
<< Dependent Types | Contents | Pointcuts and Advice >>

Bindings

Def: Binding is a relationship between two classes, where one class is declared as wrapper class and another as wrappee class. Wrapper serves as a dynamic extension to wrappee to introduce a new state to it or to adapt it to desired interface at run-time.

Binding Declaration (bind.rel)

(bind.rel.1) Binding is declared by wraps clause of a Caesar class. The declaring class becomes the wrapper and the class in the clause becomes wrappee.

(bind.rel.2) Only nested Caesar classes can be declared as wrappers.

(bind.rel.3) Wrappee class can be any Java class or a dependent type.

(bind.rel.4) Bindings are inherited by all subclasses of a class. So all subclasses of a wrapper class are also wrapper classes.

(bind.rel.5) Bindings cannot be overridden in subclasses

(bind.rel.6) A class cannot inherit bindings from two different mixins.

Example: List.1 defines a data model for simple electrical schemes. We want to adapt it to a generic Graph collaboration defined in List. 2 in order to run algorithms defined for generic graph. Therefore we define a specialization of graph ElectricGraph and establish bindings between Edge and Wire as well as between Node and Component. So Edge class in ElectricGraph is wrapper of Wire and Wire is wrappee of Edge.

Listing 1.
 
public class Wire {
   public Pin getStartPin() { ... }
   public Pin getEndPin() { ... }
   ...
}
public class Pin {
   public Component getOwner() { ... }
   public Iterator getAttachedWires() { ... }
   ...
}
public class Component {
   public int getPinCount() { ... }
   public Pin getPinByNr(int nr) { ... }   
   ...
}

Listing 2.
 
public cclass Graph {
   public cclass Edge {
      public Node getStartNode { return null; }
      public Node getEndNode { return null; }
   }
   public cclass Node {
      public Iterator getEdges() { return null; }
   }
}
cclass ElectricGraph extends Graph {
   cclass Edge wraps Wire {
       ...
   }
   cclass Node wraps Component {
      ...
   }
}

Wrappee Access (bind.wrappee)

(bind.wrappee.1) Each instance of a wrapper class contains a non-null reference to the wrappee object, which is immutable.

(bind.wrappee.2) Wrappee object can be accessed through wrappee keyword.

(bind.wrappee.3) The type of the wrappee object of a wrapper can be any subtype of the wrappee class of the wrapper.

(bind.wrappee.4) Wrapper can access only public class members of the wrappee object.

Example: The classes of ElectricGraph of List.2. must implement the methods of Edge and Node by using corresponding methods of Wire and Component. List.3 shows implementation of Edge.getStartNode(). The method uses keyword wrappee to access the corresponding instance of Wire and call its methods.

Listing 3.
 
cclass ElectricGraph {
   cclass Edge wraps Wire {
       public Node getStartNode { 
          return Node(wrappee.getPin().getOwner());  
       }
       ...
   }
   ...
}

Wrapper Creation (bind.wrapper)

(bind.wrapper.1) Wrapper classes cannot be instantiated in a normal way using new operator:

  • Instantiation of a virtual class, which statically is known to be a wrapper class is not allowed by compiler

  • Polymorphic instantiation of a wrapper class, which cannot be detected by the compiler causes runtime exception.

(bind.wrapper.2) Wrapper classes are instantiated by expression of form exp.Cls(obj), where
  • exp is an expression returning collaboration containing wrapper class Cls,
  • obj is an object, which statically known type is a subtype of the wrappee class declared for Cls.

The expression has following semantics:

  • (bind.wrapper.3) The expression returns wrapper object of class Cls of the collaboration instance, returned by exp.

  • (bind.wrapper.4) The returned wrapper object has wrappee reference to object obj.

  • (bind.wrapper.5) The expression returns always the same wrapper object for the same triple of
    • exp instance
    • obj instance
    • class Cls

  • (bind.wrapper.6) If the wrapper object for the given triple does not exist, a new wrapper object is created.

(bind.wrapper.7) Expression of form exp.getCls(o) returns corresponding wrapper object if it exists, or null if it does not exist.

Example: In List.3 Edge.getStartNode() calls Node(wrappee.getPin().getOwner()) to retrieve the wrapper of the component, to which the wire is attached. Node(..) is implicitly assumed as this.Node(..).

When this.Node(..) is called first time for a certain instance of Component, a new Node instance is created and related with that component. The later calls of this.Node(..) on the same component will always return the same node object.

Wrapper Lifecycle (bind.life)

(bind.life.1) As long as wrapper is referenced from other objects, than its wrappee and its collaboration, it must exist. Then its wrappee and collaboration must exist too.

(bind.life.2) If wrapper is not referenced from other objects, its existence depends on the existence of both its wrappee and its collaboration. When one of these two objects is not more referenced, wrapper must be destroyed, because it is not reachable.

<< Dependent Types | Contents | Pointcuts and Advice >>