Can't locate object method XX via package "1" - perl

I am well aware that there are several questions on a similar subjects but I fail to see how to apply the answers to my problem :
< Can't locate object method "idx" via package "1" >
What I don't understand is that I am using the same architecture in two packages and that it is OK in the first one... Where is the package "1" coming from ?
Here is the package that works fine :
package ObjA;
use warnings;
use strict;
use Data::Dumper;
use Carp;
use ObjB;
#CONSTRUCTOR AND INITIALISATION
sub new {
my $class = shift;
my $self = {#_};
bless($self,$class);
$self->language();
return $self;
}
sub load {
my $self = shift;
open (my $stream,"<",$self ->{name});
my #glob_xs=();
my $i = 0;
while (<$stream>){
$i += 1;
my #x = extract($stream,());
#glob_xs=(#glob_tokens,#x);
}
$self->tokens(\#glob_xs);
}
sub extract{
my ($stream,#x) = #_;
my $line = <$stream>;
chomp $line;
if ($line =~ /^\s*$/){
return #x;
}
print join("/",split("\t",$line));
my $b = ObjB::new(split("\t",$line));
push #x,$b->form;
extract_sentence($stream,#x);
}
# OBJECT ACCESSOR METHODS
sub language {$_[0]->{language}=$_[1] if defined $_[1] ; $_[0]->{language}}
1;
And here is the one that produces the error :
package ObjB;
use warnings;
use strict;
use Data::Dumper;
use Carp;
# CONSTRUCTOR AND INITIALISATION
sub new {
my $class = shift;
my $self = {#_};
bless($self,$class);
$self->idx(); # Dies here.
return $self;
}
# OBJECT ACCESSOR METHODS
sub idx {$_[0]->{idx}=$_[1] if defined $_[1] ; $_[0]->{idx}}
1;
Would it be because ObjB is called inside ObjA ? Or because they are declared in two different files ?
I truly hope someone will have an answer because I have been running in circles ...
Thank you !!

Obj::new is a method, but you call it as a subroutine.
ObjB::new(split("\t",$line));
This results in the value of first field of the line being used as the class, and that value is probably 1. You probably meant to use
ObjB->new(split("\t",$line));

Related

Perl - Can't locate object method via "Module::SUPER"

This is my first time using OOP with perl. I am in the processes of refactoring a 4k line procedural program at work. It seems pretty straight forward but I am having an issue with inheritance and SUPER.
Error message:
"Can't locate object method "New" via package "Module::SUPER" at Module.pm line 10"
I have tried, use base, parent and setting #ISA but they all get the same error. I'm sure I have to be overlooking something.
(This is not code from the program I am working on. Just an example that produces the same error)
All .pm and .pl files are in the same directory in this example. In the program I am working on the main program is in bin and the modules will be in ../modules(relative to bin).
I would assume this would be all I need to make that work:
use lib "../modules";
If I am wrong in thinking that please let me know.
Parent Module
package BaseModule;
use strict;
use warnings;
sub new {
my $class = shift;
my $self = {
ARRAY => shift,
DIVIDER => ","
};
bless ($self, $class);
return $self;
}
sub array {
my $self = shift;
if(#_) { $self->{ARRAY} = shift };
return $self->{ARRAY};
}
sub divider {
my $self = shift;
if(#_) { $self->{DIVIDER} = shift };
return $self->{DIVIDER};
}
sub testSub {
my $self = shift;
print join($self->{DIVIDER}, #{ $self->{ARRAY} } );
return 1;
}
1;
Child Module
package Module;
use strict;
use warnings;
#use base qw(BaseModule);
#require BaseModule;
#our #ISA = qw(BaseModule);
use parent qw(BaseModule);
sub new {
my $class = shift;
my $self = $class->SUPER::New(#_);
$self->{STRING} = shift;
bless ($self, $class);
return $self;
}
sub string {
my $self = shift;
if(#_) { $self->{STRING} = shift };
return $self->{STRING};
}
sub testSub {
my $self = shift;
print "$self->{STRING}:\n";
$self->SUPER::testSub();
return 1;
}
1;
Do I need to bless the child class if the parent class returns an already blessed $self?
Main Script
#!/usr/bin/perl
use strict;
use warnings;
use Module;
my $module = Module->new([1, 2, 3, 4, 5], "Example");
$module->divider(" | "); # Test Changing divider;
$module->testSub();
Any help is greatly appreciated.
"Can't locate object method "New" via package "Module::SUPER" at Module.pm line 10"
You try to call BaseModule::New whis hasn't been defined (did you mean BaseModule::new? Perl is case sensitive).
Do I need to bless the child class if the parent class returns an
already blessed $self?
No, $self at that point is already blesses (you could check that by means of Scalar::Util::blessed().

What is the preferred convention for Perl Inheritance

In the example below, I have 3 different syntax/mechanisms for defining inheritance. All of them work. Can someone tell me which one is preferred and why (yes, I know "there is more than ..."). Also, why do I need "use WB" in 1 case and not the other 2. TIA
The main -
#!/usr/local/bin/perl -w
#######################
use strict;
use River;
use Ocean;
use Lake;
my $pName = $0; $pName =~ s/.*\///; $pName =~ s/\.\w+$//;
my #sources = (Ocean->new ('Pacific', 1),
River->new ('Brazos', 0),
Lake->new ('Tahoe', 0) );
foreach (#sources) {
$_->printIfSaline ($pName);
}
The modules (Lake, River and Ocean inherit from WaterBody):
######################
# File: Lake.pm
######################
package Lake;
use strict;
use WaterBody;
our #ISA = ('WaterBody');
sub new {
my $class = shift;
$class->SUPER::new(#_)
}
sub printIfSaline {
my ($self, $prompt) = #_;
my $name = $self->getName();
my $taste = $self->isSaline() ? "salty" : "sweet";
print "$prompt: Lake $name has $taste water\n";
}
1
######################
# File: Ocean.pm
######################
package Ocean;
use strict;
use parent 'WaterBody';
sub new {
my $class = shift;
$class->SUPER::new(#_);
}
sub printIfSaline {
my ($self, $prompt) = #_;
my $name = $self->getName;
my $taste = $self->SUPER::isSaline() ? "salty" : "sweet";
print "$prompt: $name Ocean has $taste water\n";
}
1
######################
# File: River.pm
######################
package River;
use strict;
use base 'WaterBody';
sub new {
my $class = shift;
$class->SUPER::new(#_);
}
sub printIfSaline {
my ($self, $prompt) = #_;
my $name = $self->getName;
my $taste = $self->isSaline ? "salty" : "sweet";
print "$prompt: $name river has $taste water\n";
}
1
######################
# File: WaterBody.pm
######################
package WaterBody;
sub new {
my $class = shift;
my $self = {};
$self->{name} = shift;
$self->{saline} = shift;
bless $self, $class;
return $self;
}
sub getName {
my ($self) = #_;
$self->{name}
}
sub isSaline {
my ($self) = #_;
$self->{saline}
}
1
The use parent pragma sets up the #ISA at compile time. From parent
Establish an ISA relationship with base classes at compile time
When you use ParentClass; and then manually set up #ISA that happens at run time. In this case code in BEGIN, CHECK, or INIT blocks won't be able to use the inheritance hierarchy without extra work.
The use base pragma is older and parent is recommended in docs. From base
Unless you are using the fields pragma, consider this module discouraged in favor of the lighter-weight parent
Thus I'd say go with use parent.
Manipulating #ISA is the oldest way. base was the second way, and parent is even newer. So, I'd recommend parent for new projects.
use parent 'Foo::Bar';
is cleanest, although the repetitious
use Foo::Bar qw( );
our #ISA = 'Foo::Bar';
is still commonly used. The former also has the advantage of happening sooner (when the file is compiled) than the latter (when the file is executed), though that rarely matters.
base is discouraged because it silences errors that occur when a module is loaded.

Perl: How to make sure overridden method is called when accessed from within the base class

I have a base class which calls a method which is overridden in a child class, in Perl. Currently, it still calls the base class version of the method, but I want it to call the base if there is one. Here is a simplified rendition of my code:
package Test;
use strict;
use warnings;
sub Main
{
my $self = shift;
return $self->SomeFunc();
}
sub SomeFunc
{
my $self = shift;
#...
return 1;
}
package Test2;
use strict;
use warnings;
use base qw(Test);
sub SomeFunc
{
my $self = shift;
#...
return 0;
}
package main;
use Test2;
my $test = new Test2();
print $test->Main();
and I am getting a 1 when I run this!
PS my apologies, I'm not used to creating examples in working perl code, please forgive the obvious errors.
The problem would be in your constructor, but you don't have one so your code doesn't even do what you say it does
You have probably written something like
sub new {
bless {};
}
which blesses an empty hash into the current package. Instead you need to take the class name from the first parameter passed to the constructor, like this
You should also avoid using capital letters in your lexical identifiers as they are reserved for global identifiers like package names. If you must use CamelCase then at least makeSureTheFirstLetterIsLowerCase. The standard for both Perl and Python is to use the much_clearer_snake_case
Test.pm
package Test;
use strict;
use warnings;
sub new {
my $class = shift;
bless {}, $class;
}
sub main {
my $self = shift;
$self->some_func();
}
sub some_func {
my $self = shift;
'Test::some_func';
}
Test2.pm
package Test2;
use strict;
use warnings;
use parent 'Test';
sub some_func {
my $self = shift;
'Test2::some_func';
}
main.pl
use strict;
use warnings;
my $test = Test->new;
print $test->main, "\n";
$test = Test2->new;
print $test->main, "\n";
output
Test::some_func
Test2::some_func
new doesn't mean anything in perl unless you make a function with that method name.
You need to bless an object
You can either directly bless an object
my $test = { };
bless $test, "Test2";
or make a new method that does the blessing for you:
sub new{
my $class = shift;
my $test = { };
bless $test, $class;
}

Why Object is returning random values in perl

I am new in OO perl, below is the code i have written for my learning purpose but unfortunately i am not getting correct output :
#Calculation.pm
package Calculation;
sub new
{
my $class =shift;
# my $number =shift;
my $self ={};
bless ($self,$class);
return $self;
}
sub add
{
my $val_01=shift;
my $val_02=shift;
my $total = $val_01+$val_02;
return($total);
}
1;
#Test.pl
#!/usr/bin/perl
use warnings;
use strict;
use Calculation;
my $obj = Calculation->new();
my $result =$obj->add(1,2);
print"$result\n";
$result is returning a random values.
When you call $obj->add(1,2) your add sub gets 3 arguments: $obj, 1, 2. You're shifting and adding the first 2 arguments, $obj and 1. When $obj is converted to a number for addition, its memory address is used. Add 1 to that and you get a not-quite-random-but-certainly-ugly number.
You just need to add another shift at the top of sub add.
As has been pointed out, you aren't taking account of the first parameter that is passed implicitly to the method call, usually assigned to $self.
You can also omit some of the intermediate variables to simplifiy, and it is common practice to omit the return statement when the value to be returned is the last statement in the subroutine.
This variant of your code works fine
Calculation.pm
use strict;
use warnings;
package Calculation;
sub new {
my $class = shift;
bless {}, $class;
}
sub add {
my $self = shift;
my ($val_01, $val_02) = #_;
$val_01 + $val_02;
}
1;
Test.pl
use strict;
use warnings;
use Calculation;
my $obj = Calculation->new;
my $result = $obj->add(1, 2);
print "$result\n";
output
3

How do I read args passed to the constructor and args passed by `use Module` in Perl?

Currently I am making a new module and I was wondering how could I implement in my module 2 things.
We often see the use like:
use My::Module qw(something);
for example:
use CGI::Carp qw(fatalsToBrowser);
So the first question is, how do i
retrieve this, i mean wether the
user has specified anything and what
he specified ?
Second question is, How do i pass and read the args
directly on the constructor like
this:
my $my_module = My::Module->new(arg1,arg2,arg3);
AS requested on the comment the simple module test code:
package My::Module;
# $Id$
use strict;
use Carp;
sub new {
my $class = shift;
my $self = {};
$self->{ARG1} = undef;
$self->{ARG2} = undef;
$self->{ARG3} = undef;
$self->{ARG4} = undef;
bless($self,$class);
return $self;
}
sub arg1 {
my $self = shift;
if (#_) { $self->{ARG1} = shift }
return $self->{ARG1};
}
sub arg2 {
my $self = shift;
if (#_) { $self->{ARG2} = shift }
return $self->{ARG2};
}
sub arg3 {
my $self = shift;
if (#_) { $self->{ARG3} = shift }
return $self->{ARG3};
}
sub arg4 {
my $self = shift;
if (#_) { $self->{ARG4} = shift }
return $self->{ARG4};
}
sub dump {
my $self = shift;
require Data::Dumper;
my $d = Data::Dumper->new([$self], [ref $self]);
$d->Deepcopy(1);
return $d->Dump();
}
1; # so the require or use succeeds
perldoc -f use explains that the use keyword is simply loading a module during compile-time, and then calling ->import on it. The arguments a caller gave to the use statement will be passed to the import method call.
As for your second question: constructors are just methods. Getting their arguments works like it does for any other method or function, using the #_ variable.
import subroutine gets the arguments passed in a use. The following code samples should help you.
File: My/Module.pm
package My::Module;
use warnings;
use strict;
use Data::Dumper;
sub import {
my ( $package, #args ) = #_;
print Dumper \#args;
}
1;
File: module.pl
#!/usr/bin/env perl
use warnings;
use strict;
use My::Module qw(something);
If you are programming an object oriented module, you may try Moose which will save you lots of time.