I am getting:
Can't call method "test" without a package or object reference at 4.pl line 6.
And i don't know why, any ideas?
Users.pm
package Users;
sub new{
print "Created\n";
}
sub test{
print "a";
}
1;
Test.pl
BEGIN {
push #INC,"/home/baddc0re/Desktop/perl_test/";
}
use Users;
$user = new Users();
$user->test();
I suggest to you use syntax $users = Users->new() instead of new Users. You forgot to bless values inside new method. Please read perlootut under perldoc.
Users.pm
package Users;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub test {
print "a";
}
1;
MAIN
use strict;
use Users;
my $users = Users->new();
print $users->test();
Object construction in Perl doesn't work that way. The constructor has to explicitly return a reference that has been made into an object with the bless function; in fact, in Perl, this is what defines a constructor, as "new" is just another name for a subroutine and, unlike in C++, invoking a function named new does not force Perl to create an object. In this specific example, new is just returning the return value of print, which is presumably just some true value, and trying to invoke the test method on this value fails because it hasn't been blessed into any class.
Related
i'am trying to pass imported functions to another created package.
Maybe someone could help me :)
package Person;
use JSON; # i want to pass functions from this module to the package 'Employee'
sub new {
my $class = shift;
my $self = {
_name => "No Name",
};
bless $self, $class;
return $self;
}
sub setName {
my ($self, $name) = #_;
$self->{_name} = $name;
}
sub getName {
my $self = shift;
return $self->{_name};
}
1;
Now i want to use functions from the JSON Package inside this module.
package Employee;
use JSON qw( encode_json ); # This works, thx to everybody
our #ISA = qw(Person);
sub new {
my $class = shift;
my $self = Person->new();
encode_json({a=>1}); # this works now
bless $self, $class;
return $self;
}
1;
I would be nice, if someone could give me some hints.
Thanks to everybody
You're asking how to place encode_json in the Employee namespace. To do that, add the following after package Employee;:
use JSON qw( encode_json );
I'm also not sure why in the comment the OP said that he/she cannot (or does not want) put "use JSON" in the Employee package. Maybe because the Employee package file (Employee.pm) is written by someone else and cannot be modified.
Note that in Perl you can "open the Employee" package from any other code written in any file. So in your main script or the Person package file or wherever, you can do:
{ package Employee; use JSON; }
If you absolutely could not add use JSON to the Employee class because you were not sure what encoding you'd need to use, then you could pass a code reference into new:
# in Person.pm
my $e = Employee->new(\&JSON::encode_json);
# in Employee.pm
sub new {
my($class, $encoder) = #_;
...
$self->{_encoded} = $encoder->($value_to_encode);
...
return $self;
}
Again, the only reason you'd want to do this is if you dynamically needed to change which encoder you wanted to use. The solution you've adopted -- use JSON qw(encode_json) -- is the right one if you want that one function and won't need to change it.
The title is vague but I'll explain it.
I have a Perl script which uses a module named systemId
I create an object inside the script
my $id = systemId->new({_dom => "dev"});
I am planning to instantiate an object similar to the one above but inside the systemId.pm.
How do I do that?
I can't really search it on the net as I do not know what to search to begin with.
That can be done the same way it's done in a script. Similarly to how you can put the package and main:: in the same file, you can use the class in the package file once it is defined. See comments after code.
File Play.pm
package Play;
use warnings;
use strict;
sub new {
my $class = shift;
my $self = { _data => shift || 'default' };
bless $self, $class;
print "New object created.\n";
return $self;
}
sub data {
my $self = shift;
if (#_) { $self->{_data} = shift }
return $self->{_data};
}
print "Inside the package. Create object.\n";
my $obj = Play->new();
my $data = $obj->data();
print "data: $data\n";
print "\n";
1;
The script
use warnings;
use strict;
use Play;
print "In main\n";
my $obj = Play->new(25);
print "data: " . $obj->data() . "\n";
Printout when running the script
Inside the package. Create object.
New object created.
data: default
In main
New object created.
data: 25
Once the bless call executed then $self is an object of the class Play. From bless
bless REF,CLASSNAME
bless REF
This function tells the thingy referenced by REF that it is now an object in the CLASSNAME package. If CLASSNAME is omitted, the current package is used. [...]
Since we are right in the package it can be used as an object and methods called on it. From perlobj
Once we've blessed the hash referred to by $self we can start calling methods on it.
This refers to working with $self hashref, which became the object.
Note that there may be issues of initialization when it comes to creating an object and the questions of what exactly is being done and how may be important.
I can't help it but ask, what do you want to do with this?
As easy as:
my $id = systemId->new({_dom => "dev"});
You may also use...
my $id = __PACKAGE__->new({_dom => "dev"});
...but the first one is more obvious.
A new object instance could be created everwhere, including the package/class itself.
The ->new function is typically:
sub new {
my $class = shift;
my $self = bless {#_}, $class;
return $self;
}
The instance is actually created in the class module itself (using bless). There is no magic in ->new in Perl, some modules also use another name, see DateTime's ->now which does ->new(epoch => time) internally.
I followed what friedo said here.
Now, when I try to call the method testScript I get the error global symbol $obj requires explicit package name and it fails to call testScriptTwo.
use strict;
use warnings;
package Test;
use Method::Signatures;
method new {
my $obj = bless {}, $self;
return $obj;
}
method testScript {
$obj->testScriptTwo(); # Error happens here
}
method testScriptTwo { ... }
Test script:
use Test;
my $class = Test->new();
$class->testScript();
How do I make use of $obj to call methods within the package itself?
Use this instead:
method testScript {
$self->testScriptTwo();
}
The first argument is in the variable $self, not $obj
Your questions seem to indicate you do not understand the basics of scope, and how plain Perl objects work.
In Perl, when you use the ->method syntax on a package name or blessed reference, the subroutine method in that package is invoked. The first argument to the subroutine is the thing on which you invoked method.
So, if you do
My::Friend->new('Alfred');
the new subroutine in the package My::Friend receives two arguments. My::Friend and Alfred.
In a new method, it is customary to refer to the first argument as $class, but that is completely up to you. You could use $basket_case if you were so inclined:
sub new {
my $basket_case = shift;
my $basket = shift;
my $obj = bless { name => $basket } => $basket_case;
return $obj;
}
If you then invoke a method on the returned reference, that method will receive said reference as its first argument, allowing you to access data stored in that reference:
sub blurb {
my $schmorp = shift;
print $schmorp->{name}, "\n";
return;
}
Putting it all together:
#!/usr/bin/env perl
package My::Package;
use strict;
use warnings;
sub new {
my $basket_case = shift;
my $basket = shift;
my $obj = bless { name => $basket } => $basket_case;
return $obj;
}
sub blurb {
my $schmorp = shift;
print $schmorp->{name}, "\n";
return;
}
sub derp {
my $herp = shift;
printf "%s derp derp\n", $herp->{name};
return;
}
package main;
my $x = My::Package->new('Alfred');
$x->blurb;
$x->derp;
Output:
Alfred
Alfred derp derp
You need to understand these basics. Trying to put another layer of abstraction on top of the basics before understanding what is underneath will not make things any easier.
Now, if you are using Method::Signatures, it, by convention, puts that implicit first argument in a lexically scoped variable which, by default, it calls $self.
You can override that name in specific methods, and doing so in new might be a good idea to convey the fact that it doesn't expect an object instance; instead it returns a new instance.
Whatever you called that lexically scoped instance variable in one sub does not affect what it is called in another sub. For example:
#!/usr/bin/env perl
use strict;
use warnings;
sub a_number {
my $number = int(rand(10));
return $number;
}
sub square_that_number {
my $x = shift;
return $x * $x;
}
my $bzzzt = a_number();
my $trrrp = square_that_number($bzzzt);
print $trrrp, "\n";
Output:
$ ./zt.pl
36
OK, you need to backtrack a bit - you're new method is broken in the first place, which indicates that you don't really understand what's going on with OO perl.
A very simple object looks like this:
package Foo;
sub new {
#when Foo -> new is called, then 'Foo' is passed in as the class name
my ( $class ) = #_;
#create an empty hash reference - can be anything, but $self is the convention
my $self = {};
#tell perl that $self is a 'Foo' object
bless ( $self, $class );
#return the reference to your `Foo` object
return $self;
}
sub set_name {
my ( $self, $new_name ) = #_;
$self -> {name} = $new_name;
}
sub get_name {
my ( $self ) = #_;
return $self -> {name};
}
When you call this in your code:
use Foo;
my $new_instance = Foo -> new();
The class is passed into the new method, which you then use bless to create an instantiated object.
Then you can 'do stuff' with it - when you 'call' a method using -> then the first argument into the subroutine is the object reference.
So
$new_instance -> set_name ( "myname" );
print $new_instance -> get_name();
Is equivalent to:
Foo::set_name($new_instance, "myname" );
print Foo::get_name($new_instance);
You act on $new_instance which is a sort of magic hash that allows you to include code.
Method::Signatures is largely irrelevant until you understand the basics of OO. But what that does is 'simply' expand the functions within a module, such that you don't have to extract self/class etc.
By default, a method defined as method provides $self automatically. no $obj like you're using. That's a variable that's local to you new method, and simply doesn't exist outside that.
I have a module , when I am trying to get the default attribute set in initialization, is giving the following error when subroutine is being called get_name
Use of uninitialized value
sample code
package test;
#....
#....
sub new {
my ($class) = #_;
my $self = {};
bless $self,$class;
$self->_initialize();
return $self;
}
sub _initailalize {
my($self) = #_;
$self = {
_name => 'NA'
};
}
sub get_name {
return $_[0]->{_name};
}
valuable inputs required.
You are redefining $self in the local scope of _initialize and assigning a new hashref. That way you are not adding the _name key to the blessed object. After _initialize is done, your newly assigned $self (with a plain hashref) is gone. Thus in get_name it cannot access the key _name.
sub _initailalize { # btw typo here
my ($self) = #_;
$self->{_name} = 'NA';
}
If you do it like this, you will need to assign each member on an individual line.
As a suggestion, this built-in style of OO is very tedious. Try looking at Moose or it's derivatives as they are pretty powerful.
I've just started to learn about tie. I have a class named Link which I would like to do the following thing:
if fetched, return the link's address
if stored, store the new address
be able to call methods on it
So far, my code is :
package Link;
sub FETCH {
my $this = shift;
return $this->{"site"};
}
sub STORE {
my ($self,$site) = #_;
$self->{"site"} = $site;
}
sub print_method {
my $self = shift;
print $self->{"site"};
}
sub TIESCALAR {
my $class = shift;
my $link = shift;
my $this = {};
bless($this,$class);
$this->{"site"} = $link;
return $this;
}
1;
And the code I'm using to check the functionality is:
use Link;
tie my $var,"Link","http://somesite.com";
$var->print_method;
When ran, the script will terminate with the following error:
Can't call method "print_method" without a package or object reference at tietest.pl line 4..
If I understand its message correctly, $var->print_method resolves to some string upon which the method print_method is called. How could I benefit from tie, but also use the variable as an object?
EDIT: after experimenting a bit,I found out that if I return $self on fetch , I can call the methods , however , fetch won't return the address .
EDIT 2:the perl monks supplied me the solution : tied . tied will return a reference to the object VARIABLE .
By combining tied with my methods , I can accomplish everything I wanted .
Tie is the wrong tool for this job. You use ties when you want the same interface as normal data types but want to customize how the operations do their work. Since you want to access and store a string just like a scalar already does, tie doesn't do anything for you.
It looks like you want the URI module, or a subclass of it, and perhaps some overloading.
If you really need to do this, you need to use the right variable. The tie hooks up the variable you specify to the class you specify, but it's still a normal scalar (and not a reference). You have to use the object it returns if you want to call methods:
my $secret_object = tie my($normal_scalar), 'Tie::Class', #args;
$secret_object->print_method;
You can also get the secret object if you only have the tied scalar:
my $secret_object = tied $normal_scalar;
I have an entire chapter on tie in Mastering Perl.
I suggest making a normal Perl object and then overloading stringification. You lose the ability to store a value through assignment, but retain the ability to get the value out by printing the object. Once you start wanting to call methods directly, an object is probably what you want.
package Link;
use strict;
use Carp;
use overload
(
'""' => sub { shift->site },
fallback => 1,
);
sub new
{
my $class = shift;
my $self = bless {}, $class;
if(#_)
{
if(#_ == 1)
{
$self->{'site'} = shift;
}
else { croak "$class->new() expects a single URL argument" }
}
return $self;
}
sub site
{
my $self = shift;
$self->{'site'} = shift if(#_);
return $self->{'site'};
}
sub print_method
{
my $self = shift;
print $self->site, "\n";
}
1;
Example usage:
use Link;
my $link = Link->new('http://somesite.com');
print $link, "\n"; # http://somesite.com
$link->print_method; # http://somesite.com
If you really, really want assignment to work too, you can combine a normal object with overloaded stringification (Link, above) with tie:
package LinkTie;
use strict;
use Link;
sub FETCH
{
my $this = shift;
return $this->{'link'};
}
sub STORE
{
my($self, $site) = #_;
$self->{'link'}->site($site);
return $site;
}
# XXX: You could generalize this delegation with Class::Delegation or similar
sub print_method
{
my $self = shift;
print $self->{'link'}->print_method;
}
sub TIESCALAR
{
my $class = shift;
my $self = bless {}, $class;
$self->{'link'} = Link->new(#_);
return $self;
}
1;
Example usage:
tie my $link,'LinkTie','http://somesite.com';
print $link, "\n"; # http://somesite.com
$link->print_method; # http://somesite.com
$link = 'http://othersite.com';
print $link, "\n"; # http://othersite.com
$link->print_method; # http://othersite.com
This is all quite hideous and a long way to go just to get the dubious ability to assign to something that you can also call methods on and also print as-is. A standard URI object with stringification is probably a better bet.