Home > Mobile >  Perl :: Accessing Members of an Object with `use strict` Set?
Perl :: Accessing Members of an Object with `use strict` Set?

Time:09-15

I'm a Java/C/C#/python coder who is attempting his first Perl script, and I have what is prob a Perl OOO 101 question: What is the syntax to access an object's members when use strict is required?

Let me speak Java for a moment. I have this little program, all in one class file:

class Dude{
    public String name;
    public Dude(String name){
        this.name = name;
    }
    public void IntroduceYourself(){
        System.out.println("Hi, I'm " this.name);
    }
}

public toy(){
    Dude fred = new Dude("Fred");
    fred.IntroduceYourself();
}

Output on my Ubuntu machine:

me@ubuntu01:~/$ java toy
Hi, I'm Fred
me@ubuntu01:~/$

What could be simpler? I create a Dude object, then later call method Dude.IntroduceYourself(), which accesses a class member.

Okay: I have to do the exact same thing, but now in Perl (v5.26.1). Again, use strict; is required. Here's my miserable attempt:

#!/usr/bin/perl
use warnings;
use strict;

# Define a "Dude" class
package Dude;
sub new
{
    my $class = shift;
    my $self = {
                _name => shift,
               };
    bless $self, $class;
    return $self;
}
sub IntroduceYourself
{
        print("Hi, I'm $object->{name}\n");     # Compilation Error here!
}

my $object = new Dude("Fred");
$object->IntroduceYourself();

Output on the same Ubuntu machine:

me@ubuntu01:~/$ ./toyPerl.pl
Global symbol "$Dude" requires explicit package name (did you forget to declare "my $Dude"?) at ./toyPerl.pl line 18.
Execution of ./toyPerl.pl aborted due to compilation errors.
me@ubuntu01:~/$

Ugh. I've been reading a few Perl tutorials, and I see examples on how to write that IntroduceYourself() subroutine, but none with use strict as a global directive. Can anyone see what I'm doing wrong?

Also: I'm really confused about what I'll call "member functions" in Perl. In my Java example, Dude.IntroduceYourself() was defined as a method of class Dude. I intend (if possible) for IntroduceYourself() to be a function of Object/Class Dude in the Perl code. But its unclear to me how to define that. Am I misunderstanding how Perl objects handle member functions? Thank you.

CodePudding user response:

This doesn't have to do with OO, just Perl's normal strict behavior. strict forces you to declare variables, like in other languages. Without strict, undeclared objects are globals. $object is never declared, so it violates strict.

To solve this, $object must be declared. Perl's this is passed in as the first argument to a method. You need to get that argument. Perl calls this the "invocant". Typically it is called $self.

What is the syntax to access an object's members

Perl doesn't have object members like Java. A Perl object is just a reference. It doesn't even need to be a hash reference. $self->{key} is just using a hash reference, so the key has to match. $self->{_name} not $self->{name}.

sub IntroduceYourself {
    # Get the invocant off the list of arguments.
    my $self = shift;

    # Use it as a hash reference with the correct key.
    print("Hi, I'm $self->{_name}\n");
}

I intend (if possible) for IntroduceYourself() to be a function of Object/Class Dude in the Perl code. But its unclear to me how to define that.

You did it. A class is just a package. A method is just a subroutine in a package. The language does not make a distinction between subroutines and methods, nor between class and object methods. It's just how you use them.

#!/usr/bin/perl

use strict;
use warnings;

package Foo {
  sub new {
    my $class = shift;
    my($name) = @_;

    return bless { name => $name }, $class;
  }

  sub hello {
    my $self = shift;
    print "Hello my name is $self->{name}\n";
  }
}

my $foo = Foo->new("Pete");

# Called as an object method.
$foo->hello;

# Called as a subroutine.
# It works, but don't do it; it bypasses inheritance.
Foo::hello($foo);

# Called as a class method.
# It "works", but since the method expects $self to be a
# reference, not a package name, $self->{name} is... it's complicated.
Foo->hello;

Perl's OO is extremely basic. You get classes (via packages), multiple-inheritance (via @ISA), and methods (via subroutines with the invocant passed in) and that's about it. No accessors, no public, no private, no members, not even this.

If you want that, you have to write it yourself, or use an existing library. If you want all the bells and whistles and a full marching band, install Moose.


...use strict as a global directive...

use strict is not global, it is local to the current scope. The current scope is the whole file, but you can put it in a block.

{
  # strict is on in this block
  use strict;
  my $foo = 42;
  print "$foo\n";
}

# strict is off everywhere else
$bar = 23;
print "$bar\n";

Things like strict and warnings are referred to as "pragmas".

See "What's the difference between dynamic and lexical (static) scoping? Between local() and my()?".

CodePudding user response:

sub IntroduceYourself {
   my $self = shift;
   print( "Hi, I'm $self->{ _name }\n" );
}

See perlootut.


In OOP, the invocant (the value of the expression before the ./->) is passed to the method as an argument. In Java, this argument is made available as this. In Perl, this argument is made available as a leading parameter.

This means that

$o->foo( $x, $y )

is equivalent to

my $method = $o->can( 'foo' );
$method->( $o, $x, $y )

And the method looks like this:

sub foo {
   my $self = shift;
   my $x    = shift;
   my $y    = shift;

   $self->{ x } = $x;
   $self->{ y } = $y;
}
  • Related