Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

[SOLVED]: Trying to understand method calling in OOP

by Perl300 (Friar)
on May 07, 2018 at 15:37 UTC ( [id://1214157]=perlquestion: print w/replies, xml ) Need Help??

Perl300 has asked for the wisdom of the Perl Monks concerning the following question:

I am going through book "Intermediate Perl" and started with Object Oriented section. I have created a distribution Animal and inside it:

bin/pasture

use Animal; use Cow; use Horse; use Sheep; Cow->speak; Horse->speak; Sheep->speak;

lib/Animal.pm

package Animal; use 5.006; use strict; use warnings; sub speak { my $class = shift; print "a $class goes ", $class->sound, "!\n"; } sub sound { die "'You have to define sound() in a subclass' found"; }

lib/Cow.pm

package Cow; use 5.006; use strict; use warnings; use Animal; our @ISA = qw(Animal); sub sound { "moooo" }

lib/Sheep.pm

package Sheep; use 5.006; use strict; use warnings; use Animal; our @ISA = qw(Animal); sub sound { "baaaah" }

lib/Horse.pm

package Horse; use 5.006; use strict; use warnings; use Animal; our @ISA = qw(Animal); sub sound { "neigh" }

When I run ~/localperl/bin/perl -Ilib bin/pasture I get following output:

a Cow goes moooo! a Horse goes neigh! a Sheep goes baaaah!

As per book, explanation of this behavior is:

What happens when we invoke Cow−>speak now?

First, Perl constructs the argument list. Here, it’s just Cow. Then Perl looks for Cow::speak. That’s not there, so Perl checks for the inheritance array @Cow::ISA. It finds @Cow::ISA contains the single name Animal.

Perl next looks for speak inside Animal instead, as in Animal::speak. That found, Perl invokes that method with the already frozen argument list, as if we had said:

Animal::speak('Cow'); #This is the part I am having trouble understanding. How did "Cow" become an argument when I didn't specify it anywhere?

As I mentioned in comment, I am unable to understand: How did "Cow" become an argument when I didn't specify it anywhere?

Can someone please help me understand this behavior? (Forgive me for the long post.)

Replies are listed 'Best First'.
Re: Trying to understand method calling in OOP
by haukex (Archbishop) on May 07, 2018 at 16:05 UTC
    How did "Cow" become an argument when I didn't specify it anywhere?

    That's what The Arrow Operator does. From "Method Invocation" in perlobj:

    When you call a method, the thing on the left side of the arrow is passed as the first argument to the method. That means when we call Critter->new(), the new() method receives the string "Critter" as its first argument. When we call $fred->speak(), the $fred variable is passed as the first argument to speak().
      Which is why the first line in many routines is my self = shift;

        Is that why?

        moo@cow[4345]~>perl -Mstrict -le 'sub { my self = shift }' No such class self at -e line 1, near "{ my self" syntax error at -e line 1, near "my self =" Execution of -e aborted due to compilation errors.

        I tried my sundialsvc = shift; Doesn't work neither. Perl is magic.

        «The Crux of the Biscuit is the Apostrophe»

        perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: Trying to understand method calling in OOP
by stevieb (Canon) on May 07, 2018 at 15:53 UTC

    Ok, in your case, because the Cow class has its own speak() method, this line:

    Animal::speak('Cow');

    ...is actually not being called, the one in Cow is instead.

    Now, if you comment out or otherwise remove the Cow->speak() method from the Cow class, what will happen is, when you call Cow->speak(), that method will not be found, and since you are inheriting from Animal, Animal->speak() will be looked up instead, and if found, it'll call it, sending in the Cow class as the parameter to the inherited Animal->speak(). Observe:

    use warnings; use strict; package Animal; { sub speak { my ($class) = @_; if ($class eq 'Cow'){ print "$class says moooo!\n"; } } sub run { my ($class) = @_; print "$class is running away!\n"; } } package Cow; { our @ISA = qw(Animal); } package Rooster; { our @ISA = qw(Animal); } package main; Cow->speak; Rooster->run;

    Output:

    Cow says moooo! Rooster is running away!
      because the Cow class has its own speak() method

      Did the OP edit the question? Because at the moment the only speak() I see is in Animal...

        I did not change the question. Just updated the subject line to mark it as SOLVED. I do that for my reference as I am almost sure I'll come back at least once with similar/same question and then I'll have my answer with a confirmation i.e. SOLVED :-)
Re: [SOLVED]: Trying to understand method calling in OOP
by Perl300 (Friar) on May 07, 2018 at 19:06 UTC
    Thank you haukex and stevieb for your response and clarification.
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1214157]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2024-04-19 11:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found