I don't know why some people seem to be so horrified by this; sometimes it makes sense to do. Specifically, you might want to change the class to implement a conversion method, or upon getting enough information to rebless from a parent, abstract class into a concrete subclass. Depending on your semantics, you may want to maintain the same reference after a conversion, so you don't invalidate references held on to by your clients.
Let me give you an example from my CPAN module Archive::Zip. Here's the inheritance hierarchy, first:
Exporter Archive::Zip Common base class, has defs. Archive::Zip::Archive A Zip archive. Archive::Zip::Member Abstract superclass for all memb +ers. Archive::Zip::StringMember Member made from a string Archive::Zip::FileMember Member made from an external file Archive::Zip::ZipFileMember Member that lives in a zip file Archive::Zip::NewFileMember Member whose data is in a file Archive::Zip::DirectoryMember Member that is a directory
So far so good. I re-bless objects in a couple of instances. To do this, I have an inherited method called _become:
# Morph into given class (do whatever cleanup I need to do) sub _become # Archive::Zip::Member { return bless( $_[0], $_[1] ); }
This is overridden in the various member classes to add cleanup (that is, remove subclass-specific data, seek file handles to safe places, and call the SUPER::_become). For instance:
Where is this used? One of the places is in the routine that reads a Zip file. There is a loop that reads members from the file. These are initially created as Archive::Zip::ZipFileMember. But in the case of directories, there's no actual data, and we want an Archive::Zip::DirectoryMember instead. So the members that represent directories get changed to the DirectoryMember class.sub _become # Archive::Zip::FileMember { my $self = shift; my $newClass = shift; return $self if ref( $self ) eq $newClass; delete( $self->{'externalFileName'} ); delete( $self->{'fh'} ); return $self->SUPER::_become( $newClass ); }
The other place where the re-blessing happens is when someone changes the contents of a member by passing in a string. Since most of the data in the object is correct, and since clients may have references to the existing member, I just change the member (which may be of any member type) to an Archive::Zip::StringMember (if it isn't already).
Anyway, depending on the use of your objects, it may make sense. But I wouldn't do it before I did a pretty rigorous analysis of my object model.
In reply to Re: change object class during runtime
by bikeNomad
in thread change object class during runtime
by busunsl
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |