Front page | perl.perl5.porters |
Postings from May 2000
Re: overloading = [a solution]
From:
Damian Conway
Date:
May 5, 2000 14:25
Subject:
Re: overloading = [a solution]
Message ID:
200005052125.HAA04720@indy05.csse.monash.edu.au
Some time ago, Jeff Pinyan posted a demo of a handy way of grabbing control
of assignments to variables. I responded that I had a module on that, and
we decided to step outside to discuss it.
Following that discussion I'm now ready to make the module generally
available. There's a summary below. The main question is, should I find
a better name for it? If so, suggestions welcome.
Damian
-----------cut-----------cut-----------cut-----------cut-----------cut----------
NAME
Class::ifiedVars - Control assignment to scalars
DESCRIPTION
The Class::ifiedVars module exports a single subroutine named
`classify', which may be used to associate a particular class name with
a variable, in order to control the variable's behaviour when assigned to.
In its simplest form the `classify' subroutine is used like this:
classify $var => 'ClassName';
This has two effects. Firstly it enforces *type compatibility* in
assignments. That is, it restricts subsequent assignments to $var, so
that only references to objects blessed into class ClassName (or one of
its derived classes) may be assigned. Attempts to assign an incompatible
value to $var result in an exception being thrown.
Secondly, if class ClassName defines (or inherits) a method named
`ASSIGN', any subsequent assignments to $var:
$var = $newval;
will be silently converted to:
$var->ASSIGN($newval);
If ClassName doesn't have an `ASSIGN' method, the normal assignment
semantics are used (always provided, of course, $newval is type
compatible with $var).
Type-incompatible assignment semantics
If you want a variable that delegates assignments to some class's ASSIGN
method (as above), but that *doesn't* require that the assigned value be
a compatible type, you can turn off the type-compatibility checking like
so:
classify $var => 'ClassName', STRICT => 0;
Per-variable assignment semantics
You can also set up a variable with its own unique assignment semantics:
classify $var => 'ClassName', ASSIGN => $subref;
where $subref contains a reference to a subroutine.
Now any assignment to this variable will be converted to:
$subref->($var,$newval);
Note that type-compatibility will still be enforced, unless specifically
disabled:
classify $var => 'ClassName', ASSIGN => $subref, STRICT => 0;
Predefining classifiers
Some applications may require many variables classified identically.
classify $var1 => 'ClassName', ASSIGN => $subref;
classify $var2 => 'ClassName', ASSIGN => $subref;
classify $var3 => 'ClassName', ASSIGN => $subref;
classify $var4 => 'ClassName', ASSIGN => $subref;
classify $var5 => 'OtherClass', STRICT => 0;
classify $var6 => 'OtherClass', STRICT => 0;
classify $var7 => 'OtherClass', STRICT => 0;
classify $var8 => 'OtherClass', STRICT => 0;
classify $var9 => 'YetAnotherClass';
In such cases, it is more efficient to create a single subroutine to do
this. Class::ifiedVars can optionally export a subroutine named `type'
that does exactly that. It takes the same arguments as `classify',
except that, rather than taking a variable as its first argument, `type'
takes the name of the new local classifier subroutine to be created.
The subroutine that `type' creates then takes one or more variables and
classifies them using the same arguments that were originally passed to
`type'. Hence we could rewrite the above classifications:
use Class::ifiedVars 'type';
type Type1 => 'ClassName', ASSIGN => $subref;
type Type2 => 'OtherClass', STRICT => 0;
Type1 ($var1, $var2, $var3, $var4);
Type2 ($var5, $var6, $var7, $var8);
classify $var9 => 'YetAnotherClass';