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


in reply to limiting the scope of bless

That can be done easily with an object that takes charge of the reblessing and which reverts what it did at destruction time. Your illustration code would look like:

package boo; sub to_s { "a boo" }; package bar; sub to_s { "a bar" }; package main; sub doit { my $boo = shift; my $reblesser = Reblesser->new; $reblesser->rebless($boo, "bar"); print "within: ", $boo->to_s, "\n"; # "a bar" # here the scope of the reblesser ends and so the reblessing it did } my $obj = bless {}, 'boo'; print "before: ", $obj->to_s, "\n"; # "a boo" doit($obj); print "after: ", $obj->to_s, "\n"; # "a boo" again
The output should be:
$ perl reblesser.pl before: a boo [DEBUG] reblessing boo=HASH(0x102efcf8) to bar within: a bar [DEBUG] reverting blessing on bar=HASH(0x102efcf8): back to boo after: a boo
This way you just have to be sure that the scope in which you want to limit the reblessing is the same as the scope of the reblesser object. A trivial implementation of such reblesser would be:
package Reblesser; use strict; use warnings; use base qw(Class::Accessor); __PACKAGE__->mk_accessors(qw(reblessed)); use Scalar::Util qw(blessed); # reblessed holds pairs [ (object => original_package) ] sub new { my $self = shift; return $self->SUPER::new({ reblessed => [] }); } sub rebless { my $self = shift; my $obj = shift; my $package = shift; die "not blessed" unless blessed $obj; push @{$self->reblessed}, [ $obj, blessed $obj ]; warn "[DEBUG] reblessing $obj to $package\n"; return bless $obj, $package } sub DESTROY { my $self = shift; for (@{$self->reblessed}) { my ($obj, $pkg) = @$_; warn "[DEBUG] reverting blessing on $obj: back to $pkg\n"; bless $obj, $pkg; } }

Replies are listed 'Best First'.
Re^2: limiting the scope of bless
by jaa (Friar) on Apr 25, 2007 at 11:10 UTC
    Most excellent! Doh - I never thought of using scope on a separate object and invoking the $priest->DESTROY to unbless!

    Just to confirm - Is DESTROY actually and reliably called when leaving scope, rather than later in a garbage sweep? Wouldn't want the blessing to be too sticky!

    Thanks,

    Jeff

      Yes, perl does not have a background thread for its garbage collector.
Re^2: limiting the scope of bless
by aufflick (Deacon) on Apr 27, 2007 at 00:39 UTC
    Brilliant!