In the previous two chapters, we looked at basic object creation and manipulation. In this chapter, we'll look at an equally important topic: what happens when objects go away.
As you saw in Chapter 4, when the last reference to a Perl data structure goes away, Perl automatically reclaims the memory of that data structure, including destroying any links to other data. Of course, that in turn may cause other ("contained") structures to be destroyed as well.
By default, objects work in this manner because objects use the same reference structure to make more complex objects. An object built of a hash reference is destroyed when the last reference to that hash goes away. If the values of the hash elements are also references, they're similarly removed, possibly causing further destruction.
Suppose an object uses a temporary file to hold data that won't fit entirely in memory. The filehandle for this temporary file can be included as one of the object's instance variables. While the normal object destruction sequence will properly close the handle, you still have the temporary file on disk unless you take further action.
To perform the proper cleanup operations when an object is destroyed, you need to be notified when that happens. Thankfully, Perl provides such notification upon request. You can request this notification by giving the object a DESTROY method.
When the last reference to an object, say $bessie, is destroyed, Perl invokes:
$bessie->DESTROY
This method call is like most other method calls: Perl starts at the class of the object and works its way up the inheritance hierarchy until it finds a suitable method. However, unlike other method calls, there's no error if no suitable method is found.[1]
[1] Normally, your own method calls will cause an error if the method isn't found. If you want to prevent that, just put a do-nothing method into the base class.
For example, going back to the Animal class defined in Chapter 9, you can add a DESTROY method to know when objects go away, purely for debugging purposes:
## in Animal sub DESTROY { my $self = shift; print "[", $self->name, " has died.]\n"; }
Now when you create any Animals in the program, you get notification as they leave. For example:
## include animal classes from previous chapter... sub feed_a_cow_named { my $name = shift; my $cow = Cow->named($name); $cow->eat("grass"); print "Returning from the subroutine.\n"; # $cow is destroyed here } print "Start of program.\n"; my $outer_cow = Cow->named("Bessie"); print "Now have a cow named ", $outer_cow->name, ".\n"; feed_a_cow_named("Gwen"); print "Returned from subroutine.\n";
This prints:
Start of program. Now have a cow named Bessie. Gwen eats grass. Returning from the subroutine. [Gwen has died.] Returned from subroutine. [Bessie has died.]
Note that Gwen is active inside the subroutine. However, as the subroutine exits, Perl notices there are no references to Gwen; Gwen's DESTROY method is then automatically invoked, printing the Gwen has died message.
What happens at the end of the program? Since objects don't live beyond the end of the program, Perl makes one final pass over all remaining data and destroys it. This is true whether the data is held in lexical variables or package global variables. Because Bessie was still alive at the end of the program, she needed to be recycled, and so you get the message for Bessie after all other steps in the program are complete.[2]
[2] This is just after the END blocks are executed and follows the same rules as END blocks: there must be a nice exit of the program rather than an abrupt end. If Perl runs out of memory, all bets are off.