Reputation: 9804
Is unblessing Perl objects means having a dreadful design ?
If yes, can any one explain this to me ?
BTW, Here's the discussion which fired this question, check comments on the question
Upvotes: 1
Views: 377
Reputation: 73
I think unbless
is useful when I want to store the object data, but not the object data with class name; precisely, when the nature of your object data meant to be production data, rather than for object self reference to work.
package My::Pkg;
use Storable qw/dclone/;
use Data::Structure::Util qw/unbless/;
sub _distribute_private_attr {
$_[0]->{_private_attrs} = {...}
}
sub new {
my $obj = bless { Foo => [qw/bar/] };
$obj->_distribute_private_attr();
return $obj;
}
sub load {
my $cls = shift;
my $data = retrieve $_[0];
my $obj = bless $data, $cls;
$obj->_distribute_private_attr();
return $obj
}
sub save {
my $obj = shift;
my $data = unbless ( dclone $obj );
delete $data->{_private_attrs};
store $data, $_[0];
}
1;
package main;
use Some::Other::Mod;
my $obj = My::Pkg -> new;
$obj->{Bar} = "Baz";
$obj->save ("someFile");
my $obj2 = My::Pkg->load("someFile"); # Now we can do this
my $obj3 = Some::Other::Mod->load("someFile"); # or this
my $data = retrieve "someFile"; # or this
And now, the data structure stored can be used by others without messing with other class thing, yet nothing has messed with the runtime instance .
Upvotes: -1
Reputation: 118665
One application is an object implemented as a hash reference and you also wish to
overload the %{}
dereferencing operator [EDIT: and you also want to support perls older than v5.10.1 -- otherwise you should just use no overloading
.]
package Foo;
use overload '+' => sub { $_[0]->get + $_[1] },
...,
'%{}' => sub { return { foo => "bar", this => $_[0] } },
...;
Now for any $foo
that has type Foo
, trying to access an element like $foo->{$key}
will invoke your overloaded %{}
method, and your access will fail.
The workaround is to change your object's type temporarily while you access your object's member, and change it back when you are done. You could do this by unblessing your object, but it is more often done (and more easily done) by blessing it to a garbage value.
sub Foo::bar { # access 'bar' member of Foo object
my $self = shift;
# $self->{bar} will invoke Foo::{'%{}'}, and we don't wan't that
my $ref = ref $self;
unbless($self); # or bless $self, 'Not::An::Object::Name'
# now $self->{bar} is accessible
my $value = $self->{bar};
bless $self, $ref; # restore object type
return $value;
}
Another example is given in the section on "Two-face-References" in overload
I use this pattern here, for another example.
Upvotes: 4
Reputation: 126742
This is an idle and silly question. You have no purpose in mind for unbless
but have chosen it at random from an obscure CPAN module to ask why it reflects bad design. You may as well ask how to undeclare a variable that has been declared with my
. That is also quite possible in XS code, but I hope it's clearly rather stupid?
The issue I have with unbless
is that you have created a data structure -- anything from a scalar variable or a file handle to a nested hash or array -- and called bless
so that Perl know how to resolve method calls on that object
So now you want to unbless
it. That will leave the data intact, and the main difference will be that any method calls will now result in a fatal error
Can't call method ... on unblessed reference
So what was your unbless
for? If you're relying on Perl to give you this fatal error then it's just as easy to assign undef
to the object which gives rise to this fatal error instead
Can't call method ... on an undefined value
but has the advantage that your data structure may be destroyed so that the memory is released
If you want something more solid then, because references may be passed to multiple sections of code, unbless
would be an example of action at a distance which is discredited by many more people than myself
Upvotes: 1
Reputation: 111349
Needing unbless
certainly raises eyebrows. Since you can still use the object as the original data structure, it's almost never needed.
Modules that are picky about receiving unblessed hash references vs objects tend to have options to not be so picky, for example allow_blessed and convert_blessed in JSON.
Upvotes: 4