I\'m having a really hard time understanding the intersection of OO Perl and my $self = shift;
The documentation on these individual elements is great, but none of
If you call:
$myinstance->myMethod("my_parameter");
is the same that doing:
myMethod($myinstance, "my_parameter");
but if you do:
myMethod("my_parameter");
only "my_parameter" wil be passed.
THEN if inside myMethod always you do :
$self = shift @_;
$self will be the object reference when myMethod id called from an object context
but will be "my_parameter" when called from another method inside on a procedural way.
Be aware of this;
In top level-code, shift()
is short for shift(@ARGV)
. @ARGV
contains the command-line arguments.
In a sub, shift()
is short for shift(@_)
. @_
contains the sub's arguments.
So my $self = shift;
is grabbing the sub's first argument. When calling a method, the invocant (what's left of the ->
) is passed as the first parameter. In other words,
$o->method(@a)
is similar to
my $sub = $o->can('method');
$sub->($o, @a);
In that example, my $self = shift;
will assign $o
to $self
.
First off, a subroutine isn't passed the @ARGV
array. Rather all the parameters passed to a subroutine are flattened into a single list represented by @_
inside the subroutine. The @ARGV array is available at the top-level of your script, containing the command line arguments passed to you script.
Now, in Perl, when you call a method on an object, the object is implicitly passed as a parameter to the method.
If you ignore inheritance,
$obj->doCoolStuff($a, $b);
is equivalent to
doCoolStuff($obj, $a, $b);
Which means the contents of @_
in the method doCoolStuff
would be:
@_ = ($obj, $a, $b);
Now, the shift
builtin function, without any parameters, shifts an element out of the default array variable @_
. In this case, that would be $obj
.
So when you do $self = shift
, you are effectively saying $self = $obj
.
I also hope this explains how to pass other parameters to a method via the ->
notation. Continuing the example I've stated above, this would be like:
sub doCoolStuff {
# Remember @_ = ($obj, $a, $b)
my $self = shift;
my ($a, $b) = @_;
Additionally, while Moose
is a great object layer for Perl, it doesn't take away from the requirement that you need to initialize the $self
yourself in each method. Always remember this. While language like C++ and Java initialize the object reference this
implicitly, in Perl you need to do it explicitly for every method you write.