Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object-Oriented Perl constructor syntax and named parameters

I'm a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot.

package Foo;  #In Perl, the constructor is just a subroutine called new. sub new {   #I don't get what this line does at all, but I always see it. Do I need it?   my $type = shift;    #I'm turning the array of inputs into a hash, called parameters.   my %params = @_;    #I'm making a new hash called $self to store my instance variables?   my $self = {};    #I'm adding two values to the instance variables called "High" and "Low".   #But I'm not sure how $params{'High'} has any meaning, since it was an   #array, and I turned it into a hash.   $self->{'High'} = $params{'High'};   $self->{'Low'} = $params{'Low'};    #Even though I read the page on [bless][2], I still don't get what it does.   bless $self, $type; } 

And another example is:

package Bar;  sub new {   my $type = shift;    #I still don't see how I can just turn an array into a hash and expect things   #to work out for me.   my %params = @_;   my $self = [];    #Exactly where did params{'Left'} and params{'Right'} come from?   $self->[0] = $params{'Left'};   $self->[1] = $params{'Right'};    #and again with the bless.   bless $self, $type; } 

And here is the script that uses these objects:

package main;  $a = Foo->new( 'High' => 42, 'Low' => 11 ); print "High=$a->{'High'}\n"; print "Low=$a->{'Low'}\n";  $b = Bar->new( 'Left' => 78, 'Right' => 40 ); print "Left=$b->[0]\n"; print "Right=$b->[1]\n"; 

I've injected the questions/confusion that I've been having into the code as comments.

like image 517
Thomas Owens Avatar asked Nov 09 '09 19:11

Thomas Owens


People also ask

What is constructor in Perl?

The constructor method is a Perl subroutine that returns an object which is an instance of the class. It is convention to name the constructor method 'new', but it can be any valid subroutine name. The constructor method works by using the bless function on a hash reference and the class name (the package name).

What is the correct syntax for creating a new object in Perl?

shift keyword takes the package name from the default array “@_” and pass it on to the bless function. bless function is used to return a reference which ultimately becomes an object. And in the end, the constructor will finally return the instance of the class Employee(here).

What parameters are required to be passed to a class constructor in Object Oriented Programming?

A constructor can be defined to use parameters (and thus require arguments) of any type - both class types and primitive types (int, float, char, etc..) If the constructor is called like new SomeClass(someObject) , someObject is the argument passed to the constructor of SomeClass.

What is the correct syntax for defining a class in Perl?

Perl does not provide any special syntax for class definitions. A package is simply a namespace containing variables and subroutines. The only difference is that in a class, the subroutines may expect a reference to an object or the name of a class as the first argument.


1 Answers

To answer the main thrust of your question, since a hash can be initialized as a list of key => value pairs, you can send such a list to a function and then assign @_ to a hash. This is the standard way of doing named parameters in Perl.

For example,

sub foo {      my %stuff = @_;     ... }  foo( beer => 'good', vodka => 'great' ); 

This will result in %stuff in subroutine foo having a hash with two keys, beer and vodka, and the corresponding values.

Now, in OO Perl, there's some additional wrinkles. Whenever you use the arrow (->) operator to call a method, whatever was on the left side of the arrow is stuck onto the beginning of the @_ array.

So if you say Foo->new( 1, 2, 3 );

Then inside your constructor, @_ will look like this: ( 'Foo', 1, 2, 3 ).

So we use shift, which without an argument operates on @_ implicitly, to get that first item out of @_, and assign it to $type. After that, @_ has just our name/value pairs left, and we can assign it directly to a hash for convenience.

We then use that $type value for bless. All bless does is take a reference (in your first example a hash ref) and say "this reference is associated with a particular package." Alakazzam, you have an object.

Remember that $type contains the string 'Foo', which is the name of our package. If you don't specify a second argument to bless, it will use the name of the current package, which will also work in this example but will not work for inherited constructors.

like image 58
friedo Avatar answered Sep 17 '22 03:09

friedo