To clarify the problem I've written the following test code. It uses the 'lift'
method from the original post, and the tests all pass.
The only problem I see with this code is that @ISA will gradually become littered
with rubbish package names. Were Curse to define any subs that weren't just redefinitions
of subs from Player, these would remain accessible from my main program. Curse doesn't,
and won't, so I should be error free, but over time I must take a memory/performance hit.
#!/usr/bin/perl -w
use strict; use warnings;
use Test::More tests => 7;
my $player = new Player;
$player->name('Tim');
is( $player->name, 'Tim', 'name' );
$player->age( 10 );
is( $player->age, 10, 'age set' );
my $curse = new Curse::Older( $player );
is( $player->name, 'Tim (cursed)', 'name cursed' );
is( $player->age, 20, 'cursed age' );
$player->age( 20 );
is( $player->age, 40, 'age set while cursed' );
$curse->lift;
#can_ok( $player, 'name', 'player has name method'); #why does this fa
+il?
is( $player->name, 'Tim', 'name back to normal' );
is( $player->age, 20, 'age learnt while cursed' );
#---------------------------------------------------------------------
+----------
package Player;
use strict; use warnings;
sub new { bless {}, $_[0] }
sub age {
$_[1] and $_[0]->{age} = $_[1];
return $_[0]->{age}
}
sub name {
$_[1] and $_[0]->{name} = $_[1];
return $_[0]->{name}
}
#---------------------------------------------------------------------
+----------
package Curse;
use strict; use warnings;
use base 'Player';
use Class::ISA;
sub new {
my $class = shift;
my $player = shift;
return bless $player, $class;
}
sub name { $_[0]->SUPER::name . ' (cursed)' }
sub lift {
my $curse = shift;
my $pkg = __PACKAGE__;
my $old_class = ( grep {
$_ !~ /^$pkg/
} ( Class::ISA::super_path( ref( $curse ) ) ) )[0];
bless $curse, $old_class;
}
#---------------------------------------------------------------------
+----------
package Curse::Older;
use base 'Curse';
sub age { $_[0]->SUPER::age( $_[1] ) * 2}
I hope I haven't muddied the waters too much with my package names; 'curse' is not the opposite of 'bless', it's actually a package that an object (player) can be blessed into, and then unblessed back out of.
Admittedly
sub lift isn't exactly as in my original, this version also fixes a bug in my usage of __PACKAGE__.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.