Home: Perl Programming Help: Intermediate:
Problem with adding object into array



perl_newbi
Novice

Jul 3, 2011, 1:22 AM


Views: 7553
Problem with adding object into array

Hi everyone,

I have a quite strange problem with adding object into array.

Code
my $obj_class = Instance_xml->new('class'); 
my @arr_test;

for ( my $i = 0 ; $i < 5 ; $i++ )
{
$obj_class->set_class_attribute( 'port', '1111' );
$obj_class->set_class_attribute( 'name', 'port'.$i );
$obj_class->set_class_attribute( 'ip', '110.11.11.11' );
$obj_class->set_class_attribute( 'priority', 'high' );
$obj_class->set_class_attribute( 'bandwidth', '1000' );

push @arr_test,$obj_class;
}
print " Size : ".scalar(@arr_test)."\n";

for(my $i=0; $i< scalar(@arr_test);$i++)
{
print "Element $i : ".$arr_test[$i]->get_class_attribute('name')."\n";
}


I have a class name Instance_xml. I create objects of this class and trying to add those into array. Unfortunately when I added 5 objects and I checked the result that I received:


Code
Size : 5 
Element 0 : port4
Element 1 : port4
Element 2 : port4
Element 3 : port4
Element 4 : port4


It seems to be that perl added 5 times only the last created object.
Please help with and show me what I made wrong. Any ideas will be appreciated.

regards,
perl_newbi


BillKSmith
Veteran

Jul 3, 2011, 4:10 AM


Views: 7538
Re: [perl_newbi] Problem with adding object into array

You only created one object and put it in the array five times. The 'new' should be inside the loop.


Code
  
my @arr_test;

for ( my $i = 0 ; $i < 5 ; $i++ )
{
my $obj_class = Instance_xml->new('class');
$obj_class->set_class_attribute( 'port', '1111' );
$obj_class->set_class_attribute( 'name', 'port'.$i );
$obj_class->set_class_attribute( 'ip', '110.11.11.11' );
$obj_class->set_class_attribute( 'priority', 'high' );
$obj_class->set_class_attribute( 'bandwidth', '1000' );

push @arr_test,$obj_class;
}
print " Size : ".scalar(@arr_test)."\n";

for(my $i=0; $i< scalar(@arr_test);$i++)
{
print "Element $i : ".$arr_test[$i]->get_class_attribute('name')."\n";
}

Good Luck,
Bill


perl_newbi
Novice

Jul 3, 2011, 5:13 AM


Views: 7532
Re: [BillKSmith] Problem with adding object into array

Thanks for answer.
Unfortunately result of this change is the same :(


Code
 Size : 5 
Element 0 : port4
Element 1 : port4
Element 2 : port4
Element 3 : port4
Element 4 : port4


regards,
perl_newbi


BillKSmith
Veteran

Jul 3, 2011, 6:28 AM


Views: 7521
Re: [perl_newbi] Problem with adding object into array

Are you sure that you moved the 'my' the way that I showed it?


If so, the constructor 'new' is not implemented corrrectly.
Good Luck,
Bill

(This post was edited by BillKSmith on Jul 3, 2011, 6:37 AM)


perl_newbi
Novice

Jul 3, 2011, 6:37 AM


Views: 7517
Re: [BillKSmith] Problem with adding object into array

Yes Bill,
I copied all your code into my, so I couldn't make a mistake.

Do you think that problem could be in the package ?

regards,
perl_newbi


FishMonger
Veteran / Moderator

Jul 3, 2011, 6:43 AM


Views: 7516
Re: [perl_newbi] Problem with adding object into array

Try changing:

Code
push @arr_test,$obj_class;


To:

Code
push @arr_test, \$obj_class;



perl_newbi
Novice

Jul 3, 2011, 6:52 AM


Views: 7512
Re: [FishMonger] Problem with adding object into array

Hi Bill,

Right now this is a code after changes:

Code
my @arr_test; 

for ( my $i = 0 ; $i < 5 ; $i++ )
{ my $obj_class = Instance_xml->new('class');
$obj_class->set_class_attribute( 'port', '1111' );
$obj_class->set_class_attribute( 'name', 'port'.$i );
$obj_class->set_class_attribute( 'ip', '110.11.11.11' );
$obj_class->set_class_attribute( 'priority', 'high' );
$obj_class->set_class_attribute( 'bandwidth', '1000' );

push @arr_test, \$obj_class;
}
print " Size : ".scalar(@arr_test)."\n";

foreach my $ind (@arr_test)
{
print $$ind->get_class_attribute('name')."\n";
}


The result is the same:


Code
port4 
port4
port4
port4
port4


Any ideas ?

regards,
perl_newbi


FishMonger
Veteran / Moderator

Jul 3, 2011, 7:20 AM


Views: 7507
Re: [perl_newbi] Problem with adding object into array

Try this:

Code
for my $i ( 0..4 ) { 
$arr_test[$i] = Instance_xml->new('class');
$arr_test[$i]->set_class_attribute( 'port', '1111' );
$arr_test[$i]->set_class_attribute( 'name', 'port'.$i );
$arr_test[$i]->set_class_attribute( 'ip', '110.11.11.11' );
$arr_test[$i]->set_class_attribute( 'priority', 'high' );
$arr_test[$i]->set_class_attribute( 'bandwidth', '1000' );
}



perl_newbi
Novice

Jul 3, 2011, 7:26 AM


Views: 7505
Re: [FishMonger] Problem with adding object into array

Hi,

I change code

Code
my @arr_test; 

for my $i ( 0..4 )
{ $arr_test[$i] = Instance_xml->new('class');
$arr_test[$i]->set_class_attribute( 'port', '1111' );
$arr_test[$i]->set_class_attribute( 'name', 'port'.$i );
$arr_test[$i]->set_class_attribute( 'ip', '110.11.11.11' );
$arr_test[$i]->set_class_attribute( 'priority', 'high' );
$arr_test[$i]->set_class_attribute( 'bandwidth', '1000' );
}
print " Size : ".scalar(@arr_test)."\n";

foreach my $ind (@arr_test)
{
print $ind->get_class_attribute('name')."\n";
}


result is still the same:

Code
port4 
port4
port4
port4
port4



FishMonger
Veteran / Moderator

Jul 3, 2011, 7:33 AM


Views: 7503
Re: [perl_newbi] Problem with adding object into array

Are you working with a cpan module, or is this a module you wrote?

Based on this small code snippet, the only thing I can think of is that the set_class_attribute method is hard coding the number.


(This post was edited by FishMonger on Jul 3, 2011, 7:34 AM)


perl_newbi
Novice

Jul 3, 2011, 7:38 AM


Views: 7500
Re: [FishMonger] Problem with adding object into array

Hi,
This is my module. Maybe there is a problem there.
This is it:

Code
package Instance_xml; 

use diagnostics;
use warnings;
use strict;

my ( $self, $class );
my ( $instance_type, $test )
; #type - traffic, negocjacja_reply, negocjacja_request
my (@arr_instance_order); # array that have right order of instances key

my %hs_instance_class = (
'name' => '',
'port' => '',
'ip' => '',
'priority' => '',
'bandwidth' => '',
);

my %hs_instance_traffic = (
'port' => '',
'source' => '',
'destination' => '',
'packets' => '',
'priority' => '',
'desired_priority' => '',
);

my %hs_instance_negotiation_reply = (
'port' => '',
'source' => '',
'destination' => '',
'accept' => '',
'priority' => '',
'available_priority' => '',
);

my %hs_instance_negotiation_request = (
'port' => '',
'source' => '',
'destination' => '',
'accept' => '',
'priority' => '',
'desired_priority' => '',
);

# Constructor of this class:
# we send to it: type of instance (class, traffic, negotiation_reply or negotiation_request)

sub new
{
$class = shift(@_);

# print "Class: " . $class . "\n";
$self = {};

# print "Self: " . $self . "\n";
$instance_type = shift(@_);
if ( $instance_type eq 'class' )
{
%hs_instance_class = (
'name' => shift,
'port' => shift,
'ip' => shift,
'priority' => shift,
'bandwidth' => shift,
);
@arr_instance_order = qw( name port ip priority bandwidth );
}
elsif ( $instance_type eq 'traffic' )
{
%hs_instance_traffic = (
'port' => shift,
'source' => shift,
'destination' => shift,
'packets' => shift,
'priority' => shift,
'desired_bandwidth' => shift,
);
@arr_instance_order =
qw( port source destination packets priority desired_bandwidth);
}
elsif ( $instance_type eq 'negotiation_reply' )
{
%hs_instance_negotiation_reply = (
'port' => shift,
'source' => shift,
'destination' => shift,
'accept' => shift,
'priority' => shift,
'available_bandwidth' => shift,
);
@arr_instance_order =
qw( port source destination accept priority available_bandwidth);
}
elsif ( $instance_type eq 'negotiation_request' )
{
%hs_instance_negotiation_request = (
'port' => shift,
'source' => shift,
'destination' => shift,
'accept' => shift,
'priority' => shift,
'desired_bandwidth' => shift,
);
@arr_instance_order =
qw( port source destination accept priority desired_bandwidth);
}

# print $test = "I'm in Instance_xml class";

#referencja do objektu do klasy!
#referencja do objektu do klasy!
bless $self, $class;
return $self;
}

sub DESTROY
{
# print("\nCalled Instance_xmls destroy method\n");
}

####################################
####### Sekcja get #################
####################################
#get attribute from class instance
sub get_class_attribute
{
$self = shift @_;
my $key = shift @_;
return $hs_instance_class{$key};
}

#get attribute from traffic instance
sub get_traffic_attribute
{
$self = shift @_;
my $key = shift @_;
return $hs_instance_traffic{$key};
}

#get attribute from negotiation_reply instance
sub get_negotiation_reply_attribute
{
$self = shift @_;
my $key = shift @_;
return $hs_instance_negotiation_reply{$key};
}

#get attribute from negotiation_request instance
sub get_negotiation_request_attribute
{
$self = shift @_;
my $key = shift @_;
return $hs_instance_negotiation_request{$key};
}

####################################
####### Sekcja set #################
####################################

#set attribute to class instance
sub set_class_attribute
{
$self = shift @_;
my $attribute_name = shift @_;
my $attribute_value = shift @_;
$hs_instance_class{$attribute_name} = $attribute_value;
return $hs_instance_class{$attribute_name};
}

#set attribute to traffic instance
sub set_traffic_attribute
{
$self = shift @_;
my $attribute_name = shift @_;
my $attribute_value = shift @_;
$hs_instance_traffic{$attribute_name} = $attribute_value;
}

#set attribute to negotiation_reply instance
sub set_negotiation_reply_attribute
{
$self = shift @_;
my $attribute_name = shift @_;
my $attribute_value = shift @_;
$hs_instance_negotiation_reply{$attribute_name} = $attribute_value;
}

#set attribute to negotiation_request instance
sub set_negotiation_request_attribute
{
$self = shift @_;
my $attribute_name = shift @_;
my $attribute_value = shift @_;
$hs_instance_negotiation_request{$attribute_name} = $attribute_value;
}

#######################################
######## Cleaning function #############
#######################################


sub clean_class_attributes
{
$self = shift @_;
foreach my $key (%hs_instance_class)
{
$hs_instance_class{$key}='';
}
}

sub clean_traffic_attributes
{
$self = shift @_;
foreach my $key (%hs_instance_traffic)
{
$hs_instance_traffic{$key}='';
}
}

sub clean_negotiation_request_attributes
{
$self = shift @_;
foreach my $key (%hs_instance_negotiation_request)
{
$hs_instance_negotiation_request{$key}='';
}
}

sub clean_negotiation_reply_attributes
{
$self = shift @_;
foreach my $key (%hs_instance_negotiation_reply)
{
$hs_instance_negotiation_reply{$key}='';
}
}


#######################################
######## Helping function #############
#######################################

#get keys from proper instance in correct order
sub get_instance_orderer_keys
{
return @arr_instance_order;
}

sub print_instance_type
{
print "instance_type: ".$instance_type."\n";
# print $instance_type;
}
1;


Any ideas and tips for future (I'm a begginer in perls OO) will be appreciate.

regards,
perl_newbi


FishMonger
Veteran / Moderator

Jul 3, 2011, 9:02 AM


Views: 7489
Re: [perl_newbi] Problem with adding object into array

There are a number of problems with your module. For one, since hashes are unordered lists, using shift when assigning the values doesn't make any sense.

The main reason why you're not getting the desired result is because you're assigning and returning the wrong var. You need to assign and return the values to/from the $self object, not the $hs_instance_class hash.


Code
sub set_class_attribute  
{
$self = shift @_;
my $attribute_name = shift @_;
my $attribute_value = shift @_;
$self->{$attribute_name} = $attribute_value;
return $self->{$attribute_name};
}

sub get_class_attribute
{
$self = shift @_;
my $key = shift @_;
return $self->{$key};
}



perl_newbi
Novice

Jul 3, 2011, 9:15 AM


Views: 7483
Re: [FishMonger] Problem with adding object into array

Amazing - Thanks FishMonger.

Can you explain me how $self var knows from which hash it must take a value ? Could you help me with repair this module or just send me a link with 'good practice' of OO in perl ?
My idea of this module it to keep values from xml, but I have three different xml so this is the reason that I use 3 different hashes.

regards,
perl_newbi


FishMonger
Veteran / Moderator

Jul 3, 2011, 9:24 AM


Views: 7481
Re: [perl_newbi] Problem with adding object into array

What's wrong with using one of the well written and proven xml modules from cpan?


perl_newbi
Novice

Jul 3, 2011, 9:26 AM


Views: 7479
Re: [FishMonger] Problem with adding object into array

Could you be so kind and write name of this module ?
to read from xml I use XML::Simple and to write XML::Writer. Maybe you know something better ? :)

regards,
perl_newbi


FishMonger
Veteran / Moderator

Jul 3, 2011, 9:27 AM


Views: 7479
Re: [perl_newbi] Problem with adding object into array

Have you read the OO perldocs?

perlboot Perl OO tutorial for beginners
perltoot Perl OO tutorial, part 1
perltooc Perl OO tutorial, part 2
perlbot Perl OO tricks and examples


FishMonger
Veteran / Moderator

Jul 3, 2011, 9:28 AM


Views: 7478
Re: [perl_newbi] Problem with adding object into array

XML::Twig http://search.cpan.org/~mirod/XML-Twig-3.38/Twig.pm


perl_newbi
Novice

Jul 3, 2011, 9:38 AM


Views: 7473
Re: [FishMonger] Problem with adding object into array

Thank you very much :)