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;
}