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
| [reply] |
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.
| [reply] |