[trimming distribution to -internals only]
On Wed, Feb 14, 2001 at 07:44:53PM +0000, Simon Cozens wrote:
> package NuclearReactor::CoolingRod;
>
> sub new {
> Reactor->decrease_core_temperature();
> bless {}, shift
> }
>
> sub DESTROY {
> Reactor->increase_core_temperature();
> }
A better design:
package NuclearReactor::CoolingRod;
sub new {
Reactor->decrease_core_temperature();
bless { inserted => 1 }, shift;
}
sub insert {
my $self = shift;
return if $self->{inserted};
Reactor->decrease_core_temperature();
$self->{inserted} = 1;
}
sub remove {
my $self = shift;
return unless $self->{inserted};
Reactor->increase_core_temperature();
$self->{inserted} = 0;
}
sub DESTROY {
my $self = shift;
$self->remove;
}
Using object lifetime to control state is almost never a good idea,
even if you have deterministic finalization. A much better approach
is to have methods which allow holders of the object to control it,
and a finalizer (DESTROY method) which cleans up only if necessary.
A more real-world case is IO::Handle. If you want to close a handle
explicitly, you call $handle->close, not $handle->DESTROY. The
concept of closing a handle is orthogonal to the concept of the object
ceasing to exist. User code can close a handle. It can't make the
object go away -- only the garbage collector can do that.
I think that the biggest problem with DESTROY is that it is misnamed.
The name makes people think that $obj->DESTROY should destroy an object,
which it doesn't. It's rather too late to rename it to ATDESTRUCTION
or WHENDESTROYED or FINALIZE, however.
- Damien