On 19 Jun 2001 16:02:43 -0500, Nick Transier wrote:
> Given that I am trying to define an object attribute which is an array of 
> references to other object of the same type, how do I define this in the 
> $self portion of my sub new constructor? This is what I have, will this 
> work? Next is meant to hold an array of pointers or references.
> 
> sub new {
> 
>       my $invocant = shift;
>       my $class = ref($invocant) || $invocant;
>       my $self = {
>               Next,
>               @_,
>       };
>       return bless $self,$class;
> 
> }
> 
> thanks,
> -Nick
<snip />

Here is a fairly complete example of a class that uses references to
other objects of the same class (or objects that us its class as a
base).  The attribute '_friends' is a reference to an array.  It can be
accessed in many ways:

#print the first friend's name
print $self->{'_friends'}[0]->name, "\n"

#print all friend's wifes 
foreach $friend ($self->{'_friends'}) {
        print $friend->wife, "\n";
}

#print all friend's friend's names
foreach $friend ($self->{'_friends'}) {
        foreach $friends_friend ($friend->{_friends}) {
                print $friends_friend->name;
        }
}

NOTE: The deconstructor (DESTROY) is of utmost importance for classes
that refer to other objects.  In this case $fred points to $barney and
$barney points to $fred.  When $fred goes out of scope the number of
references to it in the garbage collector goes down by one; normally
this would be enough to mark it's memory space for freeing, but $barney
still has a vaild reference to it so the number of references for $fred
goes from 2 to 1 instead of 1 to 0 like it normaly would have.  When
$barney goes out of scope the same thing happens so both $fred's and
$barney's memory spaces will not be freed for use by other objects.
This is known as a "leak" or "memory leak" and having too many off them
can cause your application to crash (look at windows).


<code>
#!/usr/bin/perl

use strict;

my $fred   = Cartoon->new;
my $barney = Cartoon->new;

$fred->name('Fred');   #these are attributes they belong
$barney->name('Barney'); #to the objects that hold them

$fred->spouse('Wilma'); #so are these
$barney->spouse('Betty');

$fred->addfriend($barney); #so are these
$barney->addfriend($fred);

Cartoon->town('Bedrock'); #this, however, belongs to both $fred and
$barney

$fred->print_info;
$barney->print_info;

package Cartoon;

{ #class variables and methods
        my $town;
        sub town { return ($town =  $_[1] || $town);
        }
}

sub new {
        my $class = shift;
        $class    = ref($class) || $class;
        my $self  =  {
                '_name'    => '',
                '_spouse'  => '',
                '_friends' => [] #empty list constructor
        };

        return bless $self, $class;
}

sub name {
        my ($self, $name) = @_;
        return ($self->{_name} = $name || $self->{_name});
}

sub spouse {
        my ($self, $spouse) = @_;
        return ($self->{_spouse} = $spouse || $self->{_spouse});
}

sub addfriend {
        my ($self, $friend) = @_;

        #since self->{'_friends'} is a refernece to and array
        #we must dereference it with @{} to treat it like an
        #array
        push @{$self->{'_friends'}}, $friend;
}

sub print_info { 
        my $self = shift;

        my $name        = $self->name;
        my $spouse      = $self->spouse;
        my $town        = ref($self)->town;
        my $num_friends = @{$self->{'_friends'}};
        my @friends     = @{$self->{'_friends'}};
        my $friends;

        foreach my $friend (@friends) {
                #$friend is now a Cartoon object
                $friends .=  $friend->name;
        }

        print "$name lives in $town with $spouse, ",
              "and has $num_friends friends.\n";
        print "Their names are: $friends\n" if ($num_friends);
}

sub DESTROY {
        my $self = shift;

        #IMPORTANT: references to other objects MUST be
        #undefined before object goes out of scope otherwise
        #it is possible to have a memory leak (ie objects that
        #never get garbage collected because they still have
        #at least on vaild reference)
        undef($self->{'_friends'});
}
</code>

--
Today is Setting Orange, the 24th day of Confusion in the YOLD 3167
Fnord.


Reply via email to