32.9 Classes with Self

 < Free Open Study > 



32.9 Classes with "Self"

In §18.9, we saw how to extend imperative classes with a mechanism allowing the methods of a class to refer to each other recursively. This extension also makes sense in the purely functional setting.

We begin by abstracting counterClass on a collection of methods self appropriate for the same representation type R.

   counterClass =      λR<:CounterR.      λself: UnitCounterM R.      λ_:Unit.         {get = λs:R. s.x,          inc = λs:R. sx=succ(s.x)}         as CounterM R; 

As in §18.9, the Unit argument to the class is used to postpone evaluation during the fix operation that creates the methods of an object. The type of self includes a matching Unit abstraction.

To build an object from this class, we take the fixed point of the function counterClass and apply it to unit.

   c = {CounterR,        {state = {#x=0},         methods = fix (counterClass [CounterR]) unit}}       as Object CounterM;  c : Counter 

We next define a subclass offering a set operation, with the following interface:

   SetCounterM = λR. {get: RNat, set:RNatR, inc:RR}; 

The implementation of setCounterClass defines a set method and uses the set and get methods from self in the implementation of its inc method:

   setCounterClass =      λR<:CounterR.      λself: UnitSetCounterM R.      λ_:Unit.         let super = counterClass [R] self unit in         {get = super.get,          set = λs:R. λn:Nat. sx=n,          inc = λs:R. (self unit).set s (succ((self unit).get s))}      as SetCounterM R; 

Finally, bringing together all the mechanisms from the chapter, we can build a subclass of instrumented counters whose set operation counts the number of times that it has been called.

   InstrCounterM =     λR. {get: RNat, set:RNatR, inc:RR, accesses:RNat};   InstrCounterR = {#x:Nat,#count:Nat};   instrCounterClass =      λR<:InstrCounterR.      λself: UnitInstrCounterM R.      λ_:Unit.         let super = setCounterClass [R] self unit in         {get = super.get,          set = λs:R. λn:Nat.                  let r = super.set s n in                  rcount=succ(r.count),          inc = super.inc,          accesses = λs:R. s.count}      as InstrCounterM R; 

Note that calls to inc are included in the access count, since inc is implemented in terms of the set method from self.

To wrap up, let's build an instrumented counter object and send it some messages.

   ic = {*InstrCounterR,          {state = {#x=0,#count=0},           methods = fix (instrCounterClass [InstrCounterR]) unit}}         as Object InstrCounterM;  ic : Object InstrCounterM   sendaccesses [InstrCounterM] (sendinc [InstrCounterM] ic);  1 : Nat 

32.9.1 Exercise [Recommended, ⋆⋆⋆]

Define a subclass of instrCounterClass that adds backup and reset methods.



 < 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