Reputation: 1691
I keep getting ::
confused with ->
when calling subroutines from modules. I know that ::
is more related to paths and where the module/subroutine is and ->
is used for objects, but I don't really understand why I can seemingly interchange both and it not come up with immediate errors.
I have perl modules which are part of a larger package, e.g. FullProgram::Part1
I'm just about getting to grips with modules, but still am on wobbly grounds when it comes to Perl objects, but I've been accidentally doing this:
FullProgram::Part1::subroutine1();
instead of
FullProgram::Part1->subroutine1();
so when I've been passing a hash ref to subroutine1 and been careful about using $class/$self
to deal with the object reference and accidentally use ::
I end up pulling my hair out wondering why my hash ref seems to disappear. I have learnt my lesson, but would really like an explanation of the difference. I have read the perldocs and various websites on these but I haven't seen any comparisons between the two (quite hard to google...)
All help appreciated - always good to understand what I'm doing!
Upvotes: 8
Views: 265
Reputation: 2668
FullProgram::Part1::subroutine1();
calls the subroutine subroutine1
of the package FullProgram::Part1
with an empty parameter list while
FullProgram::Part1->subroutine1();
calls the same subroutine with the package name as the first argument (note that it gets a little bit more complex when you're subclassing). This syntax is used by constructor methods that need the class name for building objects of subclasses like
sub new {
my ($class, @args) = @_;
...
return bless $thing, $class;
}
FYI: in Perl OO you see $object->method(@args)
which calls Class::method
with the object (a blessed reference) as the first argument instead of the package/class name. In a method like this, the subroutine could work like this:
sub method {
my ($self, $foo, $bar) = @_;
$self->do_something_with($bar);
# ...
}
which will call the subroutine do_something_with
with the object as first argument again followed by the value of $bar
which was the second list element you originally passed to method
in @args
. That way the object itself doesn't get lost.
For more informations about how the inheritance tree becomes important when calling methods, please see ikegami's answer!
Upvotes: 7
Reputation: 98388
Use both!
use Module::Two;
Module::Two::->class_method();
Note that this works but also protects you against an ambiguity there; the simple
Module::Two->class_method();
will be interpreted as:
Module::Two()->class_method();
(calling the subroutine Two in Module and trying to call class_method on its return value - likely resulting in a runtime error or calling a class or instance method in some completely different class) if there happens to be a sub Two in Module - something that you shouldn't depend on one way or the other, since it's not any of your code's business what is in Module.
Upvotes: 5
Reputation: 7357
Historically, Perl dont had any OO. And functions from packages called with FullProgram::Part1::subroutine1();
sytax. Or even before with FullProgram'Part1'subroutine1();
syntax(deprecated).
Later, they implemented OOP with ->
sign, but dont changed too much actually. FullProgram::Part1->subroutine1();
calls subroutine1
and FullProgram::Part1
goes as 1st parameter. you can see usage of this when you create an object: my $cgi = CGI->new()
. Now, when you call a method from this object, left part also goes as first parameter to function: $cgi->param('')
. Thats how param
gets object he called from (usually named $self
). Thats it. ->
is hack for OOP. So as a result Perl does not have classes(packages work as them) but does have objects("objects" hacks too - they are blessed scalars).
Offtop: Also you can call with my $cgi = new CGI;
syntax. This is same as CGI->new
. Same when you say print STDOUT "text\n";
. Yeah, just just calling IOHandle::print()
.
Upvotes: 0
Reputation: 385655
There's no inherent difference between a vanilla sub and one's that's a method. It's all in how you call it.
Class::foo('a');
This will call Class::foo
. If Class::foo
doesn't exist, the inheritance tree will not be checked. Class::foo
will be passed only the provided arguments ('a'
).
It's roughly the same as: my $sub = \&Class::foo; $sub->('a');
Class->foo('a');
This will call Class::foo
, or foo
in one of its base classes if Class::foo
doesn't exist. The invocant (what's on the left of the ->
) will be passed as an argument.
It's roughly the same as: my $sub = Class->can('foo'); $sub->('Class', 'a');
Upvotes: 9