Next Previous Up Top Contents Index

5.8 Wrapper streams

5.8.1 Wrapper streams and delegation

One problem with wrapper streams is the need for a wrapper stream to intercept methods invoked by its inner stream. For example, consider two hypothetical streams, <interactive-stream> and <dialog-stream>, the latter a subclass of <wrapper-stream>. Both of these classes have a method called prompt. The <interactive-stream> class specializes read thus:

define method read (s :: <interactive-stream>, 
                    n :: <integer>,
                    #key on-end-of-stream);
  prompt(s);
  next-method()
end method; 

If a <dialog-stream> is used to wrap an <interactive-stream> then an invocation of read on the <dialog-stream> will call prompt on the inner
<interactive-stream>, not on the <dialog-stream>, as desired. The problem is that the <dialog-stream> delegates some tasks to its inner stream, but handles some other tasks itself.

Delegation by inner-streams to outer-streams is implemented by the use of the outer-stream function. The outer-stream function is used instead of the stream itself whenever a stream invokes one of its other protocol methods.

A correct implementation of the read method in the example above would be as follows:

define method read (stream :: <interactive-stream>, 
                    n :: <integer>, 
                    #key on-end-of-stream)
  prompt(s.outer-stream);
  next-method()
end method;

The initialize method on <stream> is defined to set the outer-stream slot to be the stream itself. The initialize method on <wrapper-stream> is specialized to set the outer-stream slot to be the "parent" stream:

define method initialize (stream :: <wrapper-stream>,
                          #key on, #rest all-keys);
  an-inner-stream.outer-stream := stream;
  next-method()
end method;

System and I/O Reference - 31 MAR 2000

Next Previous Up Top Contents Index