http://qs321.pair.com?node_id=701879


in reply to messing with @ISA - unblessing

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__.



- Boldra

Replies are listed 'Best First'.
Re^2: messing with @ISA - unblessing
by FunkyMonk (Chancellor) on Aug 03, 2008 at 13:04 UTC
    #can_ok( $player, 'name', 'player has name method'); #why does this fail?
    Because can_ok is looking for methods called 'name' and 'player has name method'?

    According to Test::More:

    can_ok

    can_ok($module, @methods);
    can_ok($object, @methods);

      Yep, that would be it. Thankyou!


      - Boldra
Re^2: messing with @ISA - unblessing
by shmem (Chancellor) on Aug 03, 2008 at 12:20 UTC
    #can_ok( $player, 'name', 'player has name method'); #why does this fa +il?

    Looks like a bug to me, since

    ok( $player->can('name'), 'player has name method');

    doesn't fail.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}