CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
[solved] Problem to call an object method on objects collected in an arry

 



framp
Novice


Apr 10, 2009, 4:24 AM

Post #1 of 6 (856 views)
[solved] Problem to call an object method on objects collected in an arry Can't Post

Hi,

I'm new in the world of Perl - but not in the world of programming languages and OO Wink. I want to rewrite a huge bash script and use OO Perl to learn and practice Perl. I already created a lot of OO Perl sample code to get familiar with Perl and now I'm struggling with a weired problem.

I have a collection of objects in an arry and want to loop over the collection of objects and call a method on all objects.

It works when I use a plain array. When I use Class::Std (as suggested by Conway in his Best Practices) to encapsulate the object data of my class I get

Code
Can't call method "collect" on unblessed reference at

.

That's the code which works:

Code
my $ic1 = InterfaceCollector->new( { name => "IfCollector1" } ); 
my $ic2 = InterfaceCollector->new( { name => "IfCollector2" } );

$ic1->collect(); # explicit method call
$ic2->collect();

my @collectorList;
push @collectorList, $ic1;
push @collectorList, $ic2;

foreach my $collector ( @collectorList ) { # method call to all objects in collection
$collector->collect();
}


That's the code which doesn't work:


Code
package NwDataCollector; 
use Class::Std;
use Data::Dumper;

{
my %name : ATTR( : name => 'name' );
my %collectorList : ATTR( : get => 'collectorList' );

sub BUILD {
my ( $self, $ident, $arg_ref ) = @_;
$collectorList{ ident $self} = ();
print "*** colletcorList after initialization\n";
print Data::Dumper->Dump([$collectorList{ident $self}]);
return;
}

sub run {
my ($self) = @_;
print "*** " . $self->get_name() . " started ***\n";
foreach my $collector ( $self->get_collectorList() ) {
$collector->collect(); # <----- boom, unblessed reference
}
}

sub add_collector {
my ( $self, $collector ) = @_;
print "Adding " . $collector->get_name() . "\n";
push @{$collectorList{ident $self}}, $collector;
# push @{$self->get_collectorList()},$collector;
print "*** collectorList in add_collector\n";
print Data::Dumper->Dump($collectorList{ident $self});
}

}


"Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect." Linus Benedict Torvalds, 28.9.2003

(This post was edited by framp on Apr 11, 2009, 12:23 AM)


Tumata
User


Apr 10, 2009, 4:55 AM

Post #2 of 6 (851 views)
Re: [framp] Problem to call an object method on objects collected in an arry [In reply to] Can't Post

As I understand Object in Perl is a scalar and associated with it methods. Typically scalar is hash reference. And process of associations is performed by bless. Defining this scalar and blessing are usually performed in constructor. But I don't see any method which looks like constructor in your code. So, at first you should define such method.


framp
Novice


Apr 10, 2009, 5:05 AM

Post #3 of 6 (848 views)
Re: [Tumata] Problem to call an object method on objects collected in an arry [In reply to] Can't Post

Thank you very much Tumata for your reply.

Class::Std requires to define a sub BUILD which is called under the cover when a ctor is called for a class. So the following code is the actual ctor:


Code
my ( $self, $ident, $arg_ref ) = @_;  
$collectorList{ ident $self} = ();
print "*** colletcorList after initialization\n";
print Data::Dumper->Dump([$collectorList{ident $self}]);
return;


See http://search.cpan.org/~dmuey/Class-Std-0.0.9/lib/Class/Std.pm for details.

I added a Dumper statement just before the foreach loop and get


Code
$VAR1 = bless( do{\(my $o = undef)}, 'InterfaceCollector' ); 
$VAR2 = bless( do{\(my $o = undef)}, 'InterfaceCollector' );


so the collectorList is filled with InterfaceCollectors and should be able to accept 'collect' calls.

"Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect." Linus Benedict Torvalds, 28.9.2003

(This post was edited by framp on Apr 10, 2009, 5:21 AM)


framp
Novice


Apr 10, 2009, 5:37 AM

Post #4 of 6 (844 views)
Re: [framp] Problem to call an object method on objects collected in an arry [In reply to] Can't Post

I dumped the $collector variable with Dumper and found out that it's actually still the collectList array - and not the element of the list Crazy.
Then I changed the code to

Code
	sub run { 
my ($self) = @_;
print "*** " . $self->get_name() . " started ***\n";
print Data::Dumper->Dump($collectorList{ident $self});
# foreach my $collector ( $self->get_collectorList() ) {
foreach my $collector ( @{$self->get_collectorList()} ) {
print "##############\n";
print Data::Dumper->Dump([$collector]);
$collector->collect();
}
}


and it works now. I now found the solution - but I don't understand why I have to cast to an array ...

"Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect." Linus Benedict Torvalds, 28.9.2003

(This post was edited by framp on Apr 10, 2009, 5:38 AM)


framp
Novice


Apr 11, 2009, 12:22 AM

Post #5 of 6 (825 views)
Re: [framp] Problem to call an object method on objects collected in an arry [In reply to] Can't Post

Looks like I found out why the original array is returned by the autogenerated getter method: THe getter just returns the pointer to the array and that's why it has to be casted. Therefore I created another method

Code
	sub getCollectorList { 
my ( $self, $collector ) = @_;
return @{$collectorList{ident $self}};
}

which hides the array cast and removed the generated getter.

I started to read docs about Moose which looks much better than Class::Std. Moose has for example a modifier which forces the created getter to cast the return value to the right type Smile

"Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect." Linus Benedict Torvalds, 28.9.2003

(This post was edited by framp on Apr 11, 2009, 1:42 AM)


KevinR
Veteran


Apr 11, 2009, 12:26 AM

Post #6 of 6 (823 views)
Re: [framp] Problem to call an object method on objects collected in an arry [In reply to] Can't Post

This is supposed to be a much better module than the one you are using:

http://search.cpan.org/~jdhedden/Object-InsideOut-3.54/lib/Object/InsideOut.pod

I say "supposed" because I have never used either and I am relying on the opinion of other experienced perl people that it is better. Take a look at it if interested.
-------------------------------------------------


(This post was edited by KevinR on Apr 11, 2009, 12:27 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives