[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

Reply via email to