18.10 Open Recursion Through Self

 < Free Open Study > 



18.10 Open Recursion Through Self

Most object-oriented languages actually support a more general form of recursive call between methods, known as open recursion, or late-binding of self. We can achieve this more general behavior by removing the use of fix from the class definition,

   setCounterClass =     λr:CounterRep.        λself: SetCounter.          {get = λ_:Unit. !(r.x),           set = λi:Nat.  r.x:=i,           inc = λ_:Unit. self.set (succ(self.get unit))};  setCounterClass : CounterRep  SetCounter  SetCounter 

and instead placing it in the object creation function.

   newSetCounter =     λ_:Unit. let r = {x=ref 1} in                 fix (setCounterClass r);  newSetCounter : Unit  SetCounter 

Notice that moving the use of fix changes the type of setCounterClass: instead of being abstracted just on a record of instance variables, it is also abstracted on a "self-object"; both are supplied at instantiation time.

The reason why open recursion through self is interesting is that it allows the methods of a superclass to call the methods of a subclass, even though the subclass does not exist when the superclass is being defined. In effect, we have changed the interpretation of self so that, instead of "the methods of this class," it provides access to "the methods of the class from which the current object was instantiated [which may be a subclass of this one]."

For example, suppose we want to build a subclass of our set-counters that keeps track of how many times the set method has been called. The interface of this class includes one extra operation for extracting the access count,

   InstrCounter = {get:UnitNat, set:NatUnit,                   inc:UnitUnit, accesses:UnitNat}; 

and the representation includes an instance variable for the access count:

   InstrCounterRep = {x: Ref Nat, a: Ref Nat}; 

In the definition of the instrumented counter class, the inc and get methods are copied from the setCounterClass that we defined above. The accesses method is written out in the ordinary way. In the set method, we first increment the access count and then use super to invoke the superclass's set.

   instrCounterClass =     λr:InstrCounterRep.        λself: InstrCounter.          let super = setCounterClass r self in            {get = super.get,             set = λi:Nat. (r.a:=succ(!(r.a)); super.set i),             inc = super.inc,             accesses = λ_:Unit. !(r.a)};  instrCounterClass : InstrCounterRep                        InstrCounter  InstrCounter 

Because of the open recursion through self, the call to set from the body of inc will result in the instance variable a being incremented, even though the incrementing behavior of set is defined in the subclass and the definition of inc appears in the superclass.



 < Free Open Study > 



Types and Programming Languages
Types and Programming Languages
ISBN: 0262162091
EAN: 2147483647
Year: 2002
Pages: 262

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net