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.