NAME
Class::Clone - Create a subclass or a copy of a class on-the-fly
SYNOPSIS
# Another::Package gets its methods from Some::Package,
# but to SUPER:: in Another::Pacakge will go to Another::Package::Super,
package Some::Package::Super;
sub method {
my $class = shift;
return "method";
}
package Some::Package;
sub method {
my $class = shift;
return $class->SUPER::method . "ical";
}
package Another::Package::Super;
sub method {
return "naut";
}
package main;
use Class::Clone qw(class_clone);
use Test::More qw(no_plan);
@Some::Package::ISA = qw(Some::Package::Super);
class_clone('Some::Package', 'Another::Package');
@Another::Package::ISA = qw(Another::Package::Super);
is(
Another::Package->method,
'nautical',
"Another::Package's namespace is completely independant of Some::Package"
);
DESCRIPTION
Class::Clone makes an exact clone of an existing class, whose variables and subroutines are not in any way tied back to the existing class or it's parent classes. If you change any variables in the clone, the changes don't affect the parent class. When a cloned subroutine has a call like
$self->SUPER::do_something()
the clone class's parents are traversed. This module is called Class::Clone
because this behaviour lends itself well to creating certain types of factory / polymorph classes.
(This is in contrast to importing variable or subroutine references from other packages, typically via 'Exporter'. When you do that, your copy is the original copy, so changing inherited variables affects your parent packages, and SUPER::
will call the original parent's parent, even if you change your @ISA
)
USAGE
Two functions are available for export from Class::Clone
:
- class_clone($from, $to[, %what])
-
Copy all of the symbols in package
$from
into package$to
. If a symbol already exists in$to
, it is not overwritten. The variable@ISA
is a special case: If the class you are copying to already has an@ISA
, the@ISA
in the class you are copying from will be appended to that.%what
is optional; if it is not specified, arrays, hashes, scalars, and code are cloned into$to
. If it is specified, the keys specify what to copy:- ARRAY
- HASH
- SCALAR
- CODE
The values specify how to copy that symbol table:
- clone
-
Make an exact duplicate in
$to
.If this is a subroutine (
CODE
), an exact duplicate will only be made if the subroutine belongs to the package in$from
, unless$from
's subroutine is an import itself, or comes from XS code. In those cases, the subroutine will be imported into$to
. - import
-
Import the reference into
$to
.
If a
false
value is specified (or the key is not specified at all), no copy is done. - class_subclass($from, $to[, %what])
-
Generate package
$to
as a pure subclass of$from
. If%what
is not specified, no cloning is done. If it is specified, it should be in the same format as%what
inclass_clone
. - class_clone_code($from, $to[, %what])
-
class_clone
creates it's subclass inside an eval().class_clone_code
returns an array containing the code that would be run in this eval() without executing it. You may want to use this method in a factory scenario where you want to add some of your own methods into the cloned class.
HOW SUBROUTINES ARE COPIED
When a subroutine is cloned, it is deparsed (with B::Deparse), then eval()'ed into the destination package. This is slow and potentially troublesome, but in most cases it does work and the destination subroutine's SUPER::
will be based off of the destination package. Also, global variables mentioned in the subroutine will refer to globals in the destination package, not the source. Watch out for this; in order for the cloned subroutine to work, you will have to clone, import, or specify all of those variables as well.
BUGS
This is highly experimental and may not work the way you want or the way I want.
- Some subroutines may not be copyable.
-
The fact that they are deparsed and then re-eval()ed is problematic at best. Problems with the deparsing or global variables might make a sub uncopyable. I'm concerned that FATAL warnings might cause problems in some cases but I haven't run into this yet.
- The copying of subroutines is extremely inefficient.
-
There might be some better way like directly copying the bytecode, but I haven't figured that out yet.
- There's currently no way to pick what variables to clone or reference.
- Ancestor checks are done for
sub
s, but not variables. -
When you ask to clone a subroutine, it is only cloned if the subroutine actually lives in that package; if it was imported from elsewhere, you get an import as well. It would be useful to have the same behaviour for the other data types.
SEE ALSO
Exporter, Clone, SUPER, Symbol::Table
AUTHOR
Tyler "Crackerjack" MacDonald <japh@crackerjack.net>
LICENSE
Copyright 2005 Tyler MacDonald. This is free software; you may redistribute it under the same terms as perl itself.