X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=deb-src%2Flibio-stringy-perl%2Fio-stringy-2.110%2Fdocs%2FIO%2FWrapTie.pm.html;fp=deb-src%2Flibio-stringy-perl%2Fio-stringy-2.110%2Fdocs%2FIO%2FWrapTie.pm.html;h=c89e43010b552309366f07bf7f7f78475eb29ad3;hb=d615bbbf525d490a6803e161c1063da7ee8fb9bc;hp=0000000000000000000000000000000000000000;hpb=5638bd62c66215ffc4830630a7bfcfe5cdf331d7;p=pkg-perl diff --git a/deb-src/libio-stringy-perl/io-stringy-2.110/docs/IO/WrapTie.pm.html b/deb-src/libio-stringy-perl/io-stringy-2.110/docs/IO/WrapTie.pm.html new file mode 100644 index 0000000..c89e430 --- /dev/null +++ b/deb-src/libio-stringy-perl/io-stringy-2.110/docs/IO/WrapTie.pm.html @@ -0,0 +1,435 @@ + +
+IO::WrapTie - wrap tieable objects in IO::Handle interface + + +
This is currently Alpha code, released for comments. + Please give me your feedback! + + + +
First of all, you'll need tie(), so:
+
+
+ require 5.004;
+
+
+
Function interface (experimental).
+Use this with any existing class...
+
+
+ use IO::WrapTie;
+ use FooHandle; ### implements TIEHANDLE interface
+
+
+ ### Suppose we want a "FooHandle->new(&FOO_RDWR, 2)".
+ ### We can instead say...
+
+
+ $FH = wraptie('FooHandle', &FOO_RDWR, 2);
+
+
+ ### Now we can use...
+ print $FH "Hello, "; ### traditional operator syntax...
+ $FH->print("world!\n"); ### ...and OO syntax as well!
+
+
+
OO interface (preferred).
+You can inherit from the IO::WrapTie::Slave mixin to get a
+nifty new_tie()
constructor...
+
+
+ #------------------------------
+ package FooHandle; ### a class which can TIEHANDLE
+
+
+ use IO::WrapTie;
+ @ISA = qw(IO::WrapTie::Slave); ### inherit new_tie()
+ ...
+
+
+ #------------------------------
+ package main;
+
+
+ $FH = FooHandle->new_tie(&FOO_RDWR, 2); ### $FH is an IO::WrapTie::Master
+ print $FH "Hello, "; ### traditional operator syntax
+ $FH->print("world!\n"); ### OO syntax
+
+
+
See IO::Scalar as an example. It also shows you how to create classes +which work both with and without 5.004. + + + +
Suppose you have a class FooHandle
, where...
+
+
+
+
FooHandle does not inherit from IO::Handle; that is, it performs +filehandle-like I/O, but to something other than an underlying +file descriptor. Good examples are IO::Scalar (for printing to a +string) and IO::Lines (for printing to an array of lines). + +
FooHandle implements the TIEHANDLE interface (see perltie); +that is, it provides methods TIEHANDLE, GETC, PRINT, PRINTF, +READ, and READLINE. + +
FooHandle implements the traditional OO interface of +FileHandle and IO::Handle; i.e., it contains methods like getline(), +read(), print(), seek(), tell(), eof(), etc. + +
Normally, users of your class would have two options: + + + +
Use only OO syntax, and forsake named I/O operators like 'print'. + +
Use with tie, and forsake treating it as a first-class object +(i.e., class-specific methods can only be invoked through the underlying +object via tied()... giving the object a "split personality"). + +
But now with IO::WrapTie, you can say:
+
+
+ $WT = wraptie('FooHandle', &FOO_RDWR, 2);
+ $WT->print("Hello, world\n"); ### OO syntax
+ print $WT "Yes!\n"; ### Named operator syntax too!
+ $WT->weird_stuff; ### Other methods!
+
+
+
And if you're authoring a class like FooHandle, just have it inherit
+from IO::WrapTie::Slave
and that first line becomes even prettier:
+
+
+ $WT = FooHandle->new_tie(&FOO_RDWR, 2);
+
+
+
The bottom line: now, almost any class can look and work exactly like +an IO::Handle... and be used both with OO and non-OO filehandle syntax. + + + +
Consider this example code, using classes in this distribution:
+
+
+ use IO::Scalar;
+ use IO::WrapTie;
+
+
+ $WT = wraptie('IO::Scalar',\$s);
+ print $WT "Hello, ";
+ $WT->print("world!\n");
+
+
+
In it, the wraptie() function creates a data structure as follows:
+
+
+ * $WT is a blessed reference to a tied filehandle
+ $WT glob; that glob is tied to the "Slave" object.
+ | * You would do all your i/o with $WT directly.
+ |
+ |
+ | ,---isa--> IO::WrapTie::Master >--isa--> IO::Handle
+ V /
+ .-------------.
+ | |
+ | | * Perl i/o operators work on the tied object,
+ | "Master" | invoking the TIEHANDLE methods.
+ | | * Method invocations are delegated to the tied
+ | | slave.
+ `-------------'
+ |
+ tied(*$WT) | .---isa--> IO::WrapTie::Slave
+ V /
+ .-------------.
+ | |
+ | "Slave" | * Instance of FileHandle-like class which doesn't
+ | | actually use file descriptors, like IO::Scalar.
+ | IO::Scalar | * The slave can be any kind of object.
+ | | * Must implement the TIEHANDLE interface.
+ `-------------'
+
+
+
NOTE: just as an IO::Handle is really just a blessed reference to a +traditional filehandle glob... so also, an IO::WrapTie::Master +is really just a blessed reference to a filehandle +glob which has been tied to some "slave" class. + + + +
The call to function wraptie(SLAVECLASS, TIEARGS...)
is
+passed onto IO::WrapTie::Master::new()
.
+Note that class IO::WrapTie::Master is a subclass of IO::Handle.
+
+
The IO::WrapTie::Master::new
method creates a new IO::Handle object,
+reblessed into class IO::WrapTie::Master. This object is the master,
+which will be returned from the constructor. At the same time...
+
+
The new
method also creates the slave: this is an instance
+of SLAVECLASS which is created by tying the master's IO::Handle
+to SLAVECLASS via tie(HANDLE, SLAVECLASS, TIEARGS...)
.
+This call to tie()
creates the slave in the following manner:
+
+
Class SLAVECLASS is sent the message TIEHANDLE(TIEARGS...)
; it
+will usually delegate this to SLAVECLASS::new(TIEARGS...)
, resulting
+in a new instance of SLAVECLASS being created and returned.
+
+
Once both master and slave have been created, the master is returned +to the caller. + +
Consider using an i/o operator on the master:
+
+
+ print $WT "Hello, world!\n";
+
+
+
Since the master ($WT) is really a [blessed] reference to a glob,
+the normal Perl i/o operators like print
may be used on it.
+They will just operate on the symbol part of the glob.
+
+
+
Since the glob is tied to the slave, the slave's PRINT method +(part of the TIEHANDLE interface) will be automatically invoked. + + +
If the slave is an IO::Scalar, that means IO::Scalar::PRINT will be
+invoked, and that method happens to delegate to the print()
method
+of the same class. So the real work is ultimately done by
+IO::Scalar::print().
+
+
+
+
Consider using a method on the master:
+
+
+ $WT->print("Hello, world!\n");
+
+
+
Since the master ($WT) is blessed into the class IO::WrapTie::Master,
+Perl first attempts to find a print()
method there. Failing that,
+Perl next attempts to find a print()
method in the superclass,
+IO::Handle. It just so happens that there is such a method;
+that method merely invokes the print
i/o operator on the self object...
+and for that, see above!
+
+
+
But let's suppose we're dealing with a method which isn't part
+of IO::Handle... for example:
+
+
+ my $sref = $WT->sref;
+
+
+
In this case, the intuitive behavior is to have the master delegate the +method invocation to the slave (now do you see where the designations +come from?). This is indeed what happens: IO::WrapTie::Master contains +an AUTOLOAD method which performs the delegation. + + +
So: when sref()
can't be found in IO::Handle, the AUTOLOAD method
+of IO::WrapTie::Master is invoked, and the standard behavior of
+delegating the method to the underlying slave (here, an IO::Scalar)
+is done.
+
+
+
Sometimes, to get this to work properly, you may need to create +a subclass of IO::WrapTie::Master which is an effective master for +your class, and do the delegation there. + + + +
Why not simply use the object's OO interface?
+ Because that means forsaking the use of named operators
+like print(), and you may need to pass the object to a subroutine
+which will attempt to use those operators:
+
+
+ $O = FooHandle->new(&FOO_RDWR, 2);
+ $O->print("Hello, world\n"); ### OO syntax is okay, BUT....
+
+
+ sub nope { print $_[0] "Nope!\n" }
+ X nope($O); ### ERROR!!! (not a glob ref)
+
+
+
Why not simply use tie()?
+ Because (1) you have to use tied() to invoke methods in the
+object's public interface (yuck), and (2) you may need to pass
+the tied symbol to another subroutine which will attempt to treat
+it in an OO-way... and that will break it:
+
+
+ tie *T, 'FooHandle', &FOO_RDWR, 2;
+ print T "Hello, world\n"; ### Operator is okay, BUT...
+
+
+ tied(*T)->other_stuff; ### yuck! AND...
+
+
+ sub nope { shift->print("Nope!\n") }
+ X nope(\*T); ### ERROR!!! (method "print" on unblessed ref)
+
+
+
Why a master and slave?
+ Why not simply write FooHandle to inherit from IO::Handle?
+ I tried this, with an implementation similar to that of IO::Socket.
+The problem is that the whole point is to use this with objects
+that don't have an underlying file/socket descriptor..
+Subclassing IO::Handle will work fine for the OO stuff, and fine with
+named operators if you tie()... but if you just attempt to say:
+
+
+ $IO = FooHandle->new(&FOO_RDWR, 2);
+ print $IO "Hello!\n";
+
+
+
you get a warning from Perl like:
+
+
+ Filehandle GEN001 never opened
+
+
+
because it's trying to do system-level i/o on an (unopened) file
+descriptor. To avoid this, you apparently have to tie() the handle...
+which brings us right back to where we started! At least the
+IO::WrapTie mixin lets us say:
+
+
+ $IO = FooHandle->new_tie(&FOO_RDWR, 2);
+ print $IO "Hello!\n";
+
+
+
and so is not too bad. :-)
+
+
+
+
Remember: this stuff is for doing FileHandle-like i/o on things +without underlying file descriptors. If you have an underlying +file descriptor, you're better off just inheriting from IO::Handle. + + +
Be aware that new_tie() always returns an instance of a +kind of IO::WrapTie::Master... it does not return an instance +of the i/o class you're tying to! + + +
Invoking some methods on the master object causes AUTOLOAD to delegate +them to the slave object... so it looks like you're manipulating a +"FooHandle" object directly, but you're not. + + +
I have not explored all the ramifications of this use of tie(). +Here there be dragons. + + + +
$Id: WrapTie.pm,v 2.102 2001/08/17 02:06:33 eryq Exp $ + + + +
Eryq (