perloopperl-data-structures

What is the difference in memory usage and reference counting in "has-a" and "is-a" relationship in Perl?


I read the "Programming Perl" book which is rather complicated in some places. And one of those places is the section "Instance Destructors" in the 12th chapter "Objects". This section says:

  1. Objects in Perl are destroyed when there is no more references to them.
  2. There is an opportunity to capture control just before object is going to be recycled by defining DESTROY method in its class.
  3. Although destructors are rarely needed in Perl, some objects may have, for instance, filehandles or database connections, which are outside of the memory system. So it is necessary to attend them specially.
  4. Perl does not do hierarchical destruction.

Then there is a paragraph which I failed to understand:

This only applies to inherited classes; an object that is simply contained within the current object—as, for example, one value in a larger hash—will be freed and destroyed automatically. This is one reason why containership via mere ag- gregation (sometimes called a “has-a” relationship) is often cleaner and clearer than inheritance (an “is-a” relationship).

I can't understand what it means. Does it mean that an object that IS NOT simply contained within the current object, WILL NOT be freed and destroyed automatically?

I do know that a DESTROY that is called on the garbage collection is the nearest one and only one. No other overridden DESTROY methods are called when there is no refs to an instance. But, as I understand, the same behavior is expected when a ref to an instance is placed inside another object.

Would someone be so pleasant to construe and to provide a code-example ?


UPDATE:

Actually what I was looking for, was the explanation of the This only applies to inherited classes; words which turned out to be that:

If you have an instance of a class and it has a DESTROY method than that method will override DESTROY methods of a parent class(es), but that does not apply to an object, that is in a has-a relationship with the object in question. Its DESTROY won't be overridden

Sorry for not clear question, it would better fit to the English Language and Usage. Thanks to everyone.


Solution

  • Rule 1: Objects in Perl are destroyed when there is no more references to them.

    {
      my $object = Class->new()
    }
    # there are no more references to $object
    # (it is out of scope and can't be accessed by any means)
    # Perl is free to garbage-collect it.
    

    Rule 2: There is an opportunity to capture control just before object is going to be recycled by defining DESTROY method in its class.

    package Class;
    sub new     { return bless({}, shift) }
    sub DESTROY { print STDERR "The object is destroyed" }
    
    ####
    
    {
      my $object = Class->new();
    }
    # before the object is garbage-collected, cleanup-operations should be manually performed
    # like closing down connections, solving circular references
    # any time, the object might print it's message.
    

    Rule 4: Perl does not do hierarchical destruction.

    package AnotherClass;
    use Class;
    use parent 'Class';
    sub DESTROY { print STDERR "subclass reporting dead" }
    

    Now if AnotherClass will be instantiated, only the DESTROY method of AnotherClass will be called, not the DESTROY method of Class. This is meant with the absence of a hierarchical destruction. This is obvious, as the DESTROY method overwrites the previous entry. The original DESTROY can be called manually

    Using a parent class and a child class is a IS-A relationship: AnotherClass is a Class.

    If we have YetAnotherClass:

    package YetAnotherClass;
    use Class;
    sub new {return bless({member => Class->new()}, shift) }
    
    {
       my $object = YetAnotherClass->new();
    }
    # $object goes out of scope (zero reference count) and will be destroyed.
    # Therefore, the reference count of the "member" drops to zero
    # The member will therefore be destroyed and print it's message.
    

    This is a case of aggregation (Class is a data member of YetAnotherClass), and a HAS-A relationship.