Array as instance variable

R

robert.waters

Hello,

I need to keep track of a list of items in my package/object;
currently, I am going about it like this:

sub new {
my $self = { _listofstuff => undef };
bless $self;
return $self;
}
sub dostuff {
my $self =shift;
for (my $i=0; $i<10 ;$i++) {
push @{$self->{_listofstuff}), "listitem";
}
}

Is there a better way? Using '$self->underscored-hash-item' is
tedious, but I am willing to deal with it; however, having to treat
this hash element as an array in order to use it as such (rather than
declaring it as an array to begin with) seems hackish. I would very
much love to just see '@listofstuff'.

Can't I just declare an array in the top-level scope and pass it around
as a reference from function to function? Or would this create a class
variable, shared by each instance?

Thank you very much,
Robert
(a perl OOP beginner)
 
U

Uri Guttman

rw> Also, how would I go about populating that array inside the
rw> constructor?

this is in response to BOTH of your postings. please even quote yourself
if you have to do this.

you can use ANY reference for an object, not just hashes. hashes just
are the most common and usually direct way to do perl objects. get the
book Object Oriented Perl by damian conway and learn how to make objects
out of any ref including arrays. that will also show you how to
initialize them (hint: just the same as with any array you need to
init).

uri
 
A

anno4000

Uri Guttman said:
rw> Also, how would I go about populating that array inside the
rw> constructor?

this is in response to BOTH of your postings. please even quote yourself
if you have to do this.

you can use ANY reference for an object, not just hashes. hashes just
are the most common and usually direct way to do perl objects. get the
book Object Oriented Perl by damian conway and learn how to make objects
out of any ref including arrays. that will also show you how to
initialize them (hint: just the same as with any array you need to
init).

That is an excellent solution if the array is the only data to be
kept in the object. If the array is just one field among others,
there is no other way than than to use an arrayref much like the OP
did.

Anno
 
U

Uri Guttman

rw> Also, how would I go about populating that array inside the
rw> constructor?
a> That is an excellent solution if the array is the only data to be
a> kept in the object. If the array is just one field among others,
a> there is no other way than than to use an arrayref much like the OP
a> did.

and even if he uses a hash ref for the object and it has the array ref,
there is a very simple way to clean up the code of all those
$self->{array} expressions. just assign the array ref to a lexical in
the methods and use that. it is called factoring out common (or
constant) expressions and it is a very old coding and compiling
technique. you can think of it as useful case of a temp variable (just
don't ever name it 'temp'!).

uri
 
A

anno4000

Uri Guttman said:
a> That is an excellent solution if the array is the only data to be
a> kept in the object. If the array is just one field among others,
a> there is no other way than than to use an arrayref much like the OP
a> did.

and even if he uses a hash ref for the object and it has the array ref,
there is a very simple way to clean up the code of all those
$self->{array} expressions. just assign the array ref to a lexical in
the methods and use that. it is called factoring out common (or
constant) expressions and it is a very old coding and compiling
technique. you can think of it as useful case of a temp variable (just
don't ever name it 'temp'!).

The same technique applies also when a field is a plain scalar instead
of an array (or other) reference. Instead of accessing $self->{ scalar}
repeatedly, do

my $scalar = $self->{ scalar};

and use that.

One difference is that with a reference after

my $array = $self->{ array};

you have full access to the underlying array and can change its
content through $array. You can't change the content of
$self->{ scalar} through $scalar because $scalar is a copy.

If you need that (which isn't always the case) you can use a one-shot
loop to get a lexical alias for $self->{ array}:

for my $scalar ( $self->{ scalar} ) {
# use $scalar here, including assignment
$scalar = 123; # changes $self->{ scalar}
}

That gets clumsy if you have more than one or two aliases to set up
because you need to nest a block for each one. There are a couple
of modules on CPAN that give you lexical aliases through other means
which could help there (search for "lexical alias") . However, in
that situation I would probably conclude I was trying to do too much
in a single method and change the design.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,265
Latest member
TodLarocca

Latest Threads

Top