in reply to Re: Re-blessing || Re-constructing objects
in thread Re-blessing || Re-constructing objects

Is a valid answer "never, and if I see code that re-blesses, I make sure it gets red flagged"? I didn't see that in your poll, but that's would I would check off.

Re-blessing can be very useful way to inactivate destroy your object while it hasn't been destroyed. Imagine, for example, DBI's database connection handles. For this contrived case, assume that connections never die except by explicit connection from your own side. After $dbh->disconnect, they're mostly useless. If they were blessed into another class, and already cleaned up internally, a check for connection at the beginning of each method is no longer needed. Great for performance, great for keeping your code clean. And the clean code would inspire me to add better diagnostics: instead of just "prepare on an inactive database handle", you could add "(inactive because of ->disconnect in foo.pl line 15)". Possible without reblessing, but not as nice.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

  • Comment on Re^2: Re-blessing || Re-constructing objects

Replies are listed 'Best First'.
Re^3: Re-blessing || Re-constructing objects
by blogical (Pilgrim) on Apr 18, 2006 at 02:27 UTC

    Some of this flew right over/around my head, but your point seems to be avoiding a call to DESTROY for the original class- so you re-bless them into a class whose purpose it is to recycle the object, then discard of it appropriately. Is this the same as subclassing it to override the DESTROY method, or is there extra niftiness that I'm missing?

    Writing such a class would require co-maintaining it with the parent class if you break encapsulation (as merlyn points out) but if that's not a problem, sounds good. I am interested in seeing a less contrived example of what you suggest.

    "One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
    - Henry David Thoreau, Walden

      Some of this flew right over/around my head, but your point seems to be avoiding a call to DESTROY for the original class- so you re-bless them into a class whose purpose it is to recycle the object, then discard of it appropriately. Is this the same as subclassing it to override the DESTROY method, or is there extra niftiness that I'm missing?

      I use this technique to bridge the time in between inactivation and actual destruction: the object is no longer usable (possibly only partly), but there are still references to it, so it hasn't been destroyed yet. If some state (e.g. connected or disconnected) is so important for how an object works, I think it makes sense to not store the state as a property, but by changing the class. It certainly makes programming easier.

      There are good reasons to want to inactivate an object before destruction. If you let lexical destruction handle it, you may accidentally keep your heavy active state (connection) until global destruction, which may take hours, days, or even weeks before it happens. Also, if inactivation is just a side-effect of destruction, you can't easily handle things like an ENOSPC in a close. However, when the object is no longer active, you want to be sure that using it properly fails (throws an exception). You could do this by checking the state at the beginning of each method call, but I think it's easier and makes more sense to change the class, and generate methods that croak there.

      Recycling objects doesn't work just by reblessing it. You could, however, recycle objects that you have wrapped. But you can do that in a DESTROY method too, so it's not a reblessing specific game. If you want to re-use your $self later, you can use Data::Swap to swap($self, $foo) (where $foo is blessed into the inactive state class), and then store $foo (which after the swap is what $self was before) for re-use.

      Writing such a class would require co-maintaining it with the parent class if you break encapsulation (as merlyn points out) but if that's not a problem, sounds good.

      Every line of code you write has to maintained. Reblessing can result in having fewer lines to maintain, but it can also result in having to maintain a little more. If you properly inherit methods that work in both/all states, then you don't have code duplication and isa works as expected. I'd generate the methods that croak in a foreach loop, instead of repeating the same code. And, of course, you don't have to break encapsulation. When you do, it may or may not be okay, depending on how you broke it and what part you broke.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }