Related
I would like some attributes (perhaps this is the wrong term in this context) to be private, that is, only internal for the object use - can't be read or written from the outside.
For example, think of some internal variable that counts the number of times any of a set of methods was called.
Where and how should I define such a variable?
The Moose::Manual::Attributes shows the following way to create private attributes:
has '_genetic_code' => (
is => 'ro',
lazy => 1,
builder => '_build_genetic_code',
init_arg => undef,
);
Setting init_arg means this attribute cannot be set at the constructor. Make it a rw or add writer if you need to update it.
/I3az/
You can try something like this:
has 'call_counter' => (
is => 'ro',
writer => '_set_call_counter',
);
is => 'ro' makes the attribute read only. Moose generates a getter. Your methods will use the getter for incrementing the value, like so:
sub called {
my $self = shift;
$self->_set_call_counter( $self->call_counter + 1 );
...
}
writer => '_set_call_counter' generates a setter named _set_call_counter. Moose does not support true private attributes. Outside code can, technically, call _set_call_counter. By convention, though, applications do not call methods beginning with an underscore.
I think you want MooseX::Privacy.
The perldoc tells you all you should need - it adds a new trait to your attributes allowing you to declare them as private or protected:
has config => (
is => 'rw',
isa => 'Some::Config',
traits => [qw/Private/],
);
I haven't been able to figure out a way to make Moose attributes completely private. Whenever I use has 'name' => (...); to create an attribute, it is always exposed to reading at a minimum. For items I want to be truly private, I'm using standard "my" variables inside the Moose package. For a quick example, take the following module "CountingObject.pm".
package CountingObject;
use Moose;
my $cntr = 0;
sub add_one { $cntr++; }
sub get_count { return $cntr; }
1;
Scripts that use that module have no direct access to the $cntr variable. They must use the "add_one" and "get_count" methods which act as an interface to the outside world. For example:
#!/usr/bin/perl
### Call and create
use CountingObject;
my $co = CountingObject->new();
### This works: prints 0
printf( "%s\n", $co->get_count() );
### This works to update $cntr through the method
for (1..10) { $co->add_one(); }
### This works: prints 10
printf( "%s\n", $co->get_count() );
### Direct access won't work. These would fail:
# say $cntr;
# say $co->cntr;
I'm new to Moose, but as far as I can tell, this approach provides completely private variables.
Alan W. Smith provided a private class variable with a lexical variable, but it is shared by all objects in the class. Try adding a new object to the end of the example script:
my $c1 = CountingObject->new();
printf( "%s\n", $c1->get_count() );
# also shows a count of 10, same as $co
Using MooseX:Privacy is a good answer, though if you can't, you can borrow a trick from the inside-out object camp:
package CountingObject;
use Moose;
my %cntr;
sub BUILD { my $self = shift; $cntr{$self} = 0 }
sub add_one { my $self = shift; $cntr{$self}++; }
sub get_count { my $self = shift; return $cntr{$self}; }
1;
With that, each object's counter is stored as an entry in a lexical hash. The above can be implemented a little more tersely thus:
package CountingObject;
use Moose;
my %cntr;
sub add_one { $cntr{$_[0]}++ }
sub get_count { return $cntr{$_[0]}||0 }
1;
I'm writing a module for a moose object. I would like to allow a user using this object (or myself...) add some fields on the fly as he/she desires. I can't define these fields a priori since I simply don't know what they will be.
I currently simply added a single field called extra of type hashref which is is set to rw, so users can simply put stuff in that hash:
# $obj is a ref to my Moose object
$obj->extra()->{new_thingie}="abc123"; # adds some arbitrary stuff to the object
say $obj->extra()->{new_thingie};
This works. But... is this a common practice? Any other (possibly more elegant) ideas?
Note I do not wish to create another module the extends this one, this really just for on-the-fly stuff I'd like to add.
I would probably do this via native traits:
has custom_fields => (
traits => [qw( Hash )],
isa => 'HashRef',
builder => '_build_custom_fields',
handles => {
custom_field => 'accessor',
has_custom_field => 'exists',
custom_fields => 'keys',
has_custom_fields => 'count',
delete_custom_field => 'delete',
},
);
sub _build_custom_fields { {} }
On an object you'd use this like the following:
my $val = $obj->custom_field('foo'); # get field value
$obj->custom_field('foo', 23); # set field to value
$obj->has_custom_field('foo'); # does a specific field exist?
$obj->has_custom_fields; # are there any fields?
my #names = $obj->custom_fields; # what fields are there?
my $value = $obj->delete_custom_field('foo'); # remove field value
A common use-case for stuff like this is adding optional introspectable data to exception and message classes.
If you haven't made the class immutable (there is a performance penalty for not doing that, in addition to my concerns about changing class definitions on the fly), you should be able to do that by getting the meta class for the object (using $meta = $object->meta) and using the add_attribute method in Class::MOP::Class.
#!/usr/bin/perl
package My::Class;
use Moose;
use namespace::autoclean;
package main;
my $x = My::Class->new;
my $meta = $x->meta;
$meta->add_attribute(
foo => (
accessor => 'foo',
)
);
$x->foo(42);
print $x->foo, "\n";
my $y = My::Class->new({ foo => 5 });
print $y->foo, "\n";
Output:
42
5
Just in case you want to add a method to an object and not to the whole class then have a look at something like MooseX::SingletonMethod.
E.g.
use 5.012;
use warnings;
{
package Foo;
use MooseX::SingletonMethod;
sub bar { 'bar' } # method available to all objects
}
my $foo = Foo->new;
$foo->add_singleton_method( baz => sub { 'baz!' } );
$foo->baz; # => baz!
So in above the method baz is only added to the object $foo and not to class Foo.
Hmmm... I wonder if I could implement a MooseX::SingletonAttribute?
Some previous SO answer using MooseX::SingletonMethod:
How do you replace a method of a Moose object at runtime?
How do I make a new Moose class and instantiate an object of that class at runtime?
And also this blog post maybe of use and/or interest: Easy Anonymous Objects
/I3az/
Even if it's not a good pratice to modify a class at runtime, you can simply make the meta-class mutable, add the attribute(s) and make class immutable again:
$ref->meta->make_mutable ;
$ref->meta->add_attribute($attr_name,%cfg) ;
$ref->meta->make_immmutable ;
My goal is to be able to use $obj like this:
print $obj->hello() . $obj->{foo};
And I would like to create an object inline, maybe using something like this:
my $obj = (
foo => 1,
hello => sub { return 'world' }
);
but when I try to use $obj as an object, I get an error saying that $obj has not been blessed. Is there some base class (like stdClass in PHP) I can use to bless the hash so that I can use it as an object?
For those that know JavaScript, I am trying to do the following, but in Perl:
# JS CODE BELOW
var obj = { foo: 1, hello: function () { return 'world' } };
echo obj.hello() + obj.foo;
Perl would require a little help to do this. Because it doesn't consider code references stored in hashes as "methods". Methods are implemented as entries into a package symbol table. Perl is more class-oriented than JavaScript, which proudly proclaims that it is more object-oriented (on individual objects).
In order to do that functionality, you would have to create a class that mapped references in this way. The way to get around methods in the symbol table is the AUTOLOAD method. If a package contains an AUTOLOAD subroutine, when a call is made to a blessed object that Perl cannot find in the inheritance chain, it will call AUTOLOAD and set the package-scoped (our) variable $AUTOLOAD will contain the full name of the function.
We get the name of the method called, by getting the last node (after the last '::') of the fully-qualified sub name. We look to see if there is a coderef at that location, and if there is, we can return it.
package AutoObject;
use strict;
use warnings;
use Carp;
use Params::Util qw<_CODE>;
our $AUTOLOAD;
sub AUTOLOAD {
my $method_name = substr( $AUTOLOAD, index( $AUTOLOAD, '::' ) + 2 );
my ( $self ) = #_;
my $meth = _CODE( $self->{$method_name} );
unless ( $meth ) {
Carp::croak( "object does not support method='$method_name'!" );
}
goto &$meth;
}
1;
Then you would bless the object into that class:
package main;
my $obj
= bless { foo => 1
, hello => sub { return 'world' }
}, 'AutoObject';
print $obj->hello();
Normally, in an AUTOLOAD sub I "cement" behavior. That is, I create entries into the package symbol table to avoid AUTOLOAD the next time. But that's usually for a reasonably defined class behavior.
I also designed a QuickClass which creates a package for each object declared, but that contains a lot of symbol table wrangling that now days is probably better done with Class::MOP.
Given the suggestion by Eric Strom, you could add the following code into the AutoObject package. The import sub would be called anytime somebody use-d AutoObject (with the parameter 'object').
# Definition:
sub object ($) { return bless $_[0], __PACKAGE__; };
sub import { # gets called when Perl reads 'use AutoObject;'
shift; # my name
return unless $_[0] eq 'object'; # object is it's only export
use Symbol;
*{ Symbol::qualify_to_reference( 'object', scalar caller()) }
= \&object
;
}
And then, when you wanted to create an "object literal", you could just do:
use AutoObject qw<object>;
And the expression would be:
object { foo => 1, hello => sub { return 'world' } };
You could even do:
object { name => 'World'
, hello => sub { return "Hello, $_[0]->{name}"; }
}->hello()
;
And you have an "object literal" expression. Perhaps the module would be better called Object::Literal.
A more Perlish approach is to create a separate namespace for your object's desired methods and to bless the object to make those methods available for your object. The code to do this can still be quite succint.
my $obj = bless { foo => 1 }, "bar";
sub bar::hello { return 'world' };
As gbacon suggests, if you're willing to write $obj->{hello}->() instead of $obj->hello(), you can skip the bless operation.
my $obj = { foo => 1, hello => sub { return 'world' } };
Try Hash::AsObject from CPAN.
In whatever function you're creating the object in, you need to call bless on your object in order to enable method calling.
For example:
package MyClass;
sub new
{
my $obj = {
foo => 1
};
return bless($obj, "MyClass");
}
sub hello
{
my $self = shift;
# Do stuff, including shifting off other arguments if needed
}
package main;
my $obj = MyClass::new();
print "Foo: " . $obj->{foo} . "\n";
$obj->hello();
EDIT: If you want to be able to use subroutine references to provide dynamic functionality for your objects...
First, you can create your code reference like so (within this hash constructor example):
my $obj = {
foo => 1,
hello => sub { print "Hello\n"; },
}
You can then invoke it like this:
my $obj = MyClass::new(); # or whatever
$obj->{hello}->(#myArguments);
A little cumbersome, but it works. (You might not even need the second arrow, but I'm not sure.)
$obj would be a scalar, so whatever you assign to it has to be a scalar as well. You could either say
my %obj = ( foo => 1, hello => sub { return 'world' });
or
my $obj = { foo => 1, hello => sub { return 'world' }};
The latter, with the curly braces, creates a hash reference (which is a scalar, so it can go into $obj). To get to the stuff inside a hash reference, though, you have to use the arrow operator. Something like $obj->{foo} or &{$obj->{hello}}.
Unless you need to have lists of hashes or something like that, it's generally better to use the first method.
Either way, you won't be able to say $obj->hello(). Perl uses that syntax for its own flavor of OOP, which would have the hello function in a separate package that your reference has been blessed into. Like:
package example;
sub new {} { my $result = {}; return bless $result, 'example' }
sub hello { return 'world' }
package main;
my $obj = example->new();
As you can see, the methods you can call are already defined, and it's not trivial to add more. There are magic methods you can use to do such a thing, but really, it's not worth it. &{$obj{hello}} (or &{$obj->{hello}} for a reference) is less effort than trying to make Perl work like Javascript.
It's spelled a little bit differently in Perl:
my $obj = { foo => 1, hello => sub { return "world" } };
print $obj->{hello}() . $obj->{foo};
But the code is awkward. The warning you saw about the reference not being blessed is telling you that your objects aren't implemented in the way Perl expects. The bless operator marks an object with the package in which to begin searching for its methods.
Tell us what you want to do in terms of your problem domain, and we can offer suggestions for a more natural approach in Perl.
Methods in Perl are not properties of the object like they are in Python. Methods are plain regular functions functions in a package associated with the object. Regular functions taking an extra argument for the self reference.
You cannot have dynamically created functions as methods.
Here is a quote from perldoc perlobj:
1. An object is simply a reference that happens to know which class it
belongs to.
2. A class is simply a package that happens to provide methods to deal
with object references.
3. A method is simply a subroutine that expects an object reference
(or a package name, for class methods) as the first argument.
Oh, and bless() is how you establish the connection between the reference and the package.
I recommend using Class::Struct as explained in perltoot man page.
Instead of paraphrasing the documentation, let me quote it as it explained well how this works:
"What it does is provide you a way to "declare" a class as having objects whose fields are of a specific type. The function that does this is called, not surprisingly enough, struct(). Because structures or records are not base types in Perl, each time you want to create a class to provide a record-like data object, you yourself have to define a new() method, plus separate data-access methods for each of that record's fields. You'll quickly become bored with this process. The Class::Struct::struct() function alleviates this tedium."
Still quoting from the doc is an example way on how to implement it:
use Class::Struct qw(struct);
use Jobbie; # user-defined; see below
struct 'Fred' => {
one => '$',
many => '#',
profession => 'Jobbie', # does not call Jobbie->new()
};
$ob = Fred->new(profession => Jobbie->new());
$ob->one("hmmmm");
$ob->many(0, "here");
$ob->many(1, "you");
$ob->many(2, "go");
print "Just set: ", $ob->many(2), "\n";
$ob->profession->salary(10_000);
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.
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.
.1. In Perl, the constructor is just a subroutine called new.
Yes, by convention new is a constructor. It may also perform initialization or not. new should return an object on success or throw an exception (die/croak) if an error has occurred that prevents object creation.
You can name your constructor anything you like, have as many constructors as you like, and even build bless objects into any name space you desire (not that this is a good idea).
.2. I don't get what my $type = shift; does at all, but I always see it. Do I need it?
shift with no arguments takes an argument off the head of #_ and assigns it to $type. The -> operator passes the invocant (left hand side) as the first argument to the subroutine. So this line gets the class name from the argument list. And, yes, you do need it.
.3. How does an array of inputs become the %params hash? my %params = #_;
Assignment into a hash is done in list context, with pairs of list items being grouped into as key/value pairs. So %foo = 1, 2, 3, 4;, creates a hash such that $foo{1} == 2 and $foo{3} == 4. This is typically done to create named parameters for a subroutine. If the sub is passed an odd number of arguments, an warning will be generated if warnings are enabled.
.4. What does 'my $self = {};` do?
This line creates an anonymous hash reference and assigns it to the lexically scoped variable $self. The hash reference will store the data for the object. Typically, the keys in the hash have a one-to-one mapping to the object attributes. So if class Foo has attributes 'size' and 'color', if you inspect the contents of a Foo object, you will see something like $foo = { size => 'm', color => 'black' };.
.5. Given $self->{'High'} = $params{'High'}; where does $params{'High'} come from?
This code relies on the arguments passed to new. If new was called like Foo->new( High => 46 ), then the hash created as per question 3 will have a value for the key High (46). In this case it is equivalent to saying $self->{High} = 46. But if the method is called like Foo->new() then no value will be available, and we have $self->{High} = undef.
.6. What does bless do?
bless takes a reference and associates with a particular package, so that you can use it to make method calls. With one argument, the reference is assoicated with the current package. With two arguments, the second argument specifies the package to associate the reference with. It is best to always use the two argument form, so that your constructors can be inherited by a sub class and still function properly.
Finally, I'll rewrite your hash based object accessor as I would write it using classical OO Perl.
package Foo;
use strict;
use warnings;
use Carp qw(croak);
sub new {
my $class = shift;
croak "Illegal parameter list has odd number of values"
if #_ % 2;
my %params = #_;
my $self = {};
bless $self, $class;
# This could be abstracted out into a method call if you
# expect to need to override this check.
for my $required (qw{ name rank serial_number });
croak "Required parameter '$required' not passed to '$class' constructor"
unless exists $params{$required};
}
# initialize all attributes by passing arguments to accessor methods.
for my $attrib ( keys %params ) {
croak "Invalid parameter '$attrib' passed to '$class' constructor"
unless $self->can( $attrib );
$self->$attrib( $params{$attrib} );
}
return $self;
}
Your question is not about OO Perl. You are confused about data structures.
A hash can be initialized using a list or array:
my #x = ('High' => 42, 'Low' => 11);
my %h = #x;
use Data::Dumper;
print Dumper \%h;
$VAR1 = {
'Low' => 11,
'High' => 42
};
When you invoke a method on a blessed reference, the reference is prepended to the argument list the method receives:
#!/usr/bin/perl
package My::Mod;
use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Indent = 0;
sub new { bless [] => shift }
sub frobnicate { Dumper(\#_) }
package main;
use strict;
use warnings;
my $x = My::Mod->new;
# invoke instance method
print $x->frobnicate('High' => 42, 'Low' => 11);
# invoke class method
print My::Mod->frobnicate('High' => 42, 'Low' => 11);
# call sub frobnicate in package My::Mod
print My::Mod::frobnicate('High' => 42, 'Low' => 11);
Output:
$VAR1 = [bless( [], 'My::Mod' ),'High',42,'Low',11];
$VAR1 = ['My::Mod','High',42,'Low',11];
$VAR1 = ['High',42,'Low',11];
Some points that haven't been dealt with yet:
In Perl, the constructor is just a
subroutine called new.
Not quite. Calling the constructor new is just a convention. You can call it anything you like. There is nothing special about that name from perl's point of view.
bless $self, $type;
Both of your examples don't return the result of bless explicitly. I hope that you know that they do so implicitly anyway.
If you assign an array to a hash, perl treats alternating elements in the array as keys and values. Your array is look at like
my #array = (key1, val1, key2, val2, key3, val3, ...);
When you assign that to %hash, you get
my %hash = #array;
# %hash = ( key1 => val1, key2 => val2, key3 => val3, ...);
Which is another way of saying that in perl list/hash construction syntax, "," and "=>" mean the same thing.
In Perl, all arguments to subroutines are passed via the predefined array #_.
The shift removes and returns the first item from the #_ array. In Perl OO, this is the method invocant -- typically a class name for constructors and an object for other methods.
Hashes flatten to and can be initialized by lists. It's a common trick to emulate named arguments to subroutines. e.g.
Employee->new(name => 'Fred Flintstone', occupation => 'quarry worker');
Ignoring the class name (which is shifted off) the odd elements become hash keys and the even elements become the corresponding values.
The my $self = {} creates a new hash reference to hold the instance data. The bless function is what turns the normal hash reference $self into an object. All it does is add some metadata that identifies the reference as belonging to the class.
Yes, I know that I'm being a bit of a necromancer here, but...
While all of these answers are excellent, I thought I'd mention Moose. Moose makes constructors easy (package Foo;use Moose; automatically provides a constructor called new (although the name "new" can be overridden if you'd like)) but doesn't take away any configurability if you need it.
Once I looked through the documentation for Moose (which is pretty good overall, and there are a lot more tutorial snippets around if you google appropriately), I never looked back.
I understand one uses the "bless" keyword in Perl inside a class's "new" method:
sub new {
my $self = bless { };
return $self;
}
But what exactly is "bless" doing to that hash reference ?
In general, bless associates an object with a class.
package MyClass;
my $object = { };
bless $object, "MyClass";
Now when you invoke a method on $object, Perl know which package to search for the method.
If the second argument is omitted, as in your example, the current package/class is used.
For the sake of clarity, your example might be written as follows:
sub new {
my $class = shift;
my $self = { };
bless $self, $class;
}
EDIT: See kixx's good answer for a little more detail.
bless associates a reference with a package.
It doesn't matter what the reference is to, it can be to a hash (most common case), to an array (not so common), to a scalar (usually this indicates an inside-out object), to a regular expression, subroutine or TYPEGLOB (see the book Object Oriented Perl: A Comprehensive Guide to Concepts and Programming Techniques by Damian Conway for useful examples) or even a reference to a file or directory handle (least common case).
The effect bless-ing has is that it allows you to apply special syntax to the blessed reference.
For example, if a blessed reference is stored in $obj (associated by bless with package "Class"), then $obj->foo(#args) will call a subroutine foo and pass as first argument the reference $obj followed by the rest of the arguments (#args). The subroutine should be defined in package "Class". If there is no subroutine foo in package "Class", a list of other packages (taken form the array #ISA in the package "Class") will be searched and the first subroutine foo found will be called.
Short version: it's marking that hash as attached to the current package namespace (so that that package provides its class implementation).
This function tells the entity referenced by REF that it is now an object in the CLASSNAME package, or the current package if CLASSNAME is omitted. Use of the two-argument form of bless is recommended.
Example:
bless REF, CLASSNAME
bless REF
Return Value
This function returns the reference to an object blessed into CLASSNAME.
Example:
Following is the example code showing its basic usage, the object reference is created by blessing a reference to the package's class −
#!/usr/bin/perl
package Person;
sub new
{
my $class = shift;
my $self = {
_firstName => shift,
_lastName => shift,
_ssn => shift,
};
# Print all the values just for clarification.
print "First Name is $self->{_firstName}\n";
print "Last Name is $self->{_lastName}\n";
print "SSN is $self->{_ssn}\n";
bless $self, $class;
return $self;
}
What specifically distinguishes a bless-ed referent internally is that the SV for the reference (stored in the scalar) picks up an additional FLAGS value (OBJECT), and also a STASH which carries the package name (with a few other differences)
perl -MDevel::Peek -wE'
package Pack { sub func { return { a=>1 } } };
package Class { sub new { return bless { A=>10 } } };
$vp = Pack::func(); print Dump $vp; say"---";
$obj = Class->new; print Dump $obj'
Prints, with the same (and irrelevant for this) parts suppressed
SV = IV(0x12d5530) at 0x12d5540
REFCNT = 1
FLAGS = (ROK)
RV = 0x12a5a68
SV = PVHV(0x12ab980) at 0x12a5a68
REFCNT = 1
FLAGS = (SHAREKEYS)
...
SV = IV(0x12a5ce0) at 0x12a5cf0
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 1
---
SV = IV(0x12cb8b8) at 0x12cb8c8
REFCNT = 1
FLAGS = (PADMY,ROK)
RV = 0x12c26b0
SV = PVHV(0x12aba00) at 0x12c26b0
REFCNT = 1
FLAGS = (OBJECT,SHAREKEYS) <--
STASH = 0x12d5300 "Class" <--
...
SV = IV(0x12c26b8) at 0x12c26c8
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 10
With that it is known to the interpreter that
this is an object
what package it belongs to
and this informs its use.
For example, when dereferencing on that variable is encountered ($obj->name), a sub with that name is sought in the package (or hierarchy), the object is passed as the first argument, etc.
I will try to provide an answer here since the ones here didn't quite click for me at the time I was initially writing this(warning, this answer is fairly poorly structured, feel free to skip over the parts that are not particularly useful to you).
Perl's bless function associates the specified reference with a package name string, and making the arrow operator of the blessed reference look for the method in the package associated with the reference, and if it does not find it, it continues looking using the #ISA array if there is one(this is beyond the scope of this post).
Why would we need this?
Let's begin by expressing an example in JavaScript:
(() => {
//'use strict'; // uncomment to fix the bug mentioned below.
class Animal {
constructor(args) {
console.log(this);
this.name = args.name;
this.sound = args.sound;
}
}
/* This is left for historical reasons,
* modern JavaScript engines no longer allow you to
* call class constructors without using new.
*
* var animal = Animal({
* 'name': 'Jeff',
* 'sound': 'bark'
* });
* console.log(animal.name + ', ' + animal.sound); // seems good
* console.log(window.name); // my window's name is Jeff?
*/
// as of recently, Animal constructor cannot be called without using the new operator.
var animal = new Animal({
'name': 'Jeff',
'sound': 'bark'
});
console.log(animal.name + ', ' + animal.sound); // still fine.
console.log("window's name: " + window.name); // undefined
})();
Now let's look at the desugared version of the class construct:
(() => {
// 'use strict'; // uncomment to fix bug.
var Animal = function(args) {
this.name = args.name;
this.sound = args.sound;
return this; // implicit context hashmap
};
/**
* The bug left for historical reasons,
* should still work now in modern web developer consoles.
*
* var animal = Animal({
* 'name': 'Jeff',
* 'sound': 'Bark'
* });
* console.log(animal.name + ', ' + animal.sound); // seems good
* console.log("The window's name is: " + window.name); // my window's name is Jeff?
*/
// the new operator causes the "this" inside methods to refer to the animal
// rather than the global scope, so the bug mentioned above does not occur.
var animal = new Animal({
'name': 'Jeff',
'sound': 'bark'
});
console.log(animal.sound);
console.log(window.name); // the name has not been changed by the constructor.
})();
The Animal's constructor function takes an Object of properties and returns an Animal with those properties, or if you forgot to put the new keyword, it will return the whole global context(which is window inside the browser developer console).
Perl has no "this" nor "new" nor "class", but it can still have a function that behaves similarly. We won't have a constructor nor a prototype, but we will be able to create new animals and modify their individual properties.
# immediatly invoked subroutine execution(IIFE).
(sub {
my $Animal = (sub {
return {
'name' => $_[0]{'name'},
'sound' => $_[0]{'sound'}
};
});
my $animal = $Animal->({
'name' => 'Jeff',
'sound' => 'bark'
});
print $animal->{sound};
})->();
Now, we have a problem: What if we want the animal to perform the sounds by themselves rather than having to print what their voice is directly. That is, we want a function performSound that prints the animal's own sound.
One way to do this is by giving each instance of an Animal its own performSound subroutine reference.
# self contained scope
(sub {
my $Animal = (sub {
$name = $_[0]{'name'};
$sound = $_[0]{'sound'};
return {
'name' => $name,
'sound' => $sound,
'performSound' => sub {
print $sound . "\n";
}
};
});
my $animal = $Animal->({
'name' => 'Jeff',
'sound' => 'bark'
});
$animal->{'performSound'}();
})->();
This is usually not what we want because performSound is put as a completely new subroutine reference for each animal that is constructed. Constructing 10000 animals would potentially allocate 10000 performSound subroutines. We want to have a single subroutine performSound that is used by all Animal instances that look up their own sound and print it.
(() => {
'use strict';
/* a function that creates an Animal constructor which can be used to create animals */
var Animal = (() => {
/* function is important, as fat arrow does not have "this" and will not be bound to Animal. */
var InnerAnimal = function(args) {
this.name = args.name;
this.sound = args.sound;
};
/* defined once and all animals use the same single function call */
InnerAnimal.prototype.performSound = function() {
console.log(this.name);
};
return InnerAnimal;
})();
var animal = new Animal({
'sound': 'bark',
'name': 'Jeff'
});
animal.performSound(); // Jeff
})();
Here is where the parallel to Perl kinda stops.
JavaScript's new operator is not optional, without it, "this" inside object methods contaminates the global scope:
(() => {
// uncommenting this prevents unintentional
// contamination of the global scope, and throws a TypeError instead.
// 'use strict';
var Person = function() {
this.name = "Sam";
};
// var wrong = Person(); // oops! we have overwritten window.name or global.main.
// console.log(window.name); // my window's name is Sam?
var correct = new Person; // person's name is actually stored in the person now.
})();
We want to have one function for each Animal that looks up that animal's own sound rather than hardcoding it at construction.
Blessing lets us use the package's subroutines rather than having to attach a subroutine ref to each object, it also makes ref refer to the more meaningful package name(such as Animal) as the name for the what the object is rather than a boring HASH or whatever other referent you chose to bless:
package Animal;
sub new {
my $packageRef = $_[0];
my $name = $_[1]->{'name'};
my $sound = $_[1]->{'sound'};
my $this = {
'name' => $name,
'sound' => $sound
};
bless($this, $packageRef);
return $this;
}
# all animals use the same performSound to look up their sound.
sub performSound {
my $this = shift;
my $sound = $this->{'sound'};
print $sound . "\n";
}
package main;
my $animal = Animal->new({
'name' => 'Cat',
'sound' => 'meow'
});
print("The animal's ref is: " . ref($animal) . "\n");
$animal->performSound();
Summary/TL;DR:
Perl has no "this", "class", nor "new".
Blessing an object to a package gives that object a reference to the package.
Using the arrow operator to invoke a method of a blessed referent($blessedObject->method(...arguments)) is often the same as calling Package::method($blessedObject, ...arguments), but if method is not found, it will continue looking using the #ISA of the package which is beyond the scope of this post.
You can in fact create new classes at runtime, as long as you either violate strict 'refs' or use eval, here's a demonstration of how it can be done:
#!/usr/bin/perl
use warnings;
use strict;
print('Enter the name for the class(eg Greeter): $ ');
my $class_name = <>;
chomp $class_name;
print('Enter the name of the method(eg greet): $ ');
my $method_name = <>;
chomp $method_name;
no strict 'refs';
# The line below violates strict 'refs'.
*{$class_name . '::new'} = sub {
my $self = bless {}, $_[0];
return $self;
};
use strict 'refs';
no strict 'refs';
# The line below violates strict 'refs'
*{$class_name . '::' . $method_name} = sub {
print("Hello, World!\n");
};
use strict 'refs';
my $instance = ($class_name)->new();
$instance->$method_name();
Why the confusion?:
One reason why bless is confusing is because there are effectively three ways of calling a package
Through A::a(), as a package subroutine.
Through A->a(), as a package subroutine, but that gets __PACKAGE__ passed as the first argument implicitly before the other arguments.
Through $a->a() with a blessed $a into A.
The code below illustrates this:
# | Illustrates catching 3 distinct ways of calling a package's member.
package Test;
sub new {
return bless {}, __PACKAGE__;
}
sub runTest {
if (ref($_[0]) eq __PACKAGE__) {
# | $_[0] is the blessed reference.
# | Despite being called with "->", $_[1] is NOT "Test"(__PACKAGE__).
print("Test::runTest was called through a blessed reference call(\$instance->runTest().\n");
} elsif ($_[0] eq __PACKAGE__) {
# | $_[0] is "Test"(__PACKAGE__), but we can't determine for sure whether it was -> or ::.
print("Test::runTest was called through Test->runTest() or through Test::runTest() with 'Test' as the first argument.\n");
} else {
# | $_[0] is neither a blessed reference nor "Test"(__PACKAGE__), so it can't be an arrow call.
print "Test::runTest was called through Test::runTest()\n";
}
}
package main;
my $test = Test->new();
$test->runTest();
Test->runTest();
Test::runTest();
Test::runTest('Test'); # <- Same as "Test->runTest();"
Test::runTest($test); # <- Same as "$test->runTest();"
Another reason is that unlike JavaScript, Python, which can have multiple classes with different name but different definitions/methods/properties, Perl classes have unique(ref $obj), as there can only be one package with a specific name at any given time, and #ISA takes a bit to get used to.
My final reason is that packages are less tangible than classes in other scripting languages where you can store a reference to the class itself inside a variable through the assignment operator, whereas in Perl not only can you not store references to the class(you can only refer to packages through their name strings), but trying to refer to a package through a name stored inside a variable (eg String[$method]) seems impossible without violating strict 'refs' or using eval.
Anyway hopefully somebody will find this post useful.
Note: this is a fairly old attempt at an answer, I have tried to clean up the amount of naive and embarassing/pointless/distracting statements, and adding more useful examples to help understand the concept, but it is still far from what I would like it to be(it is still fairly frustrating to re-read).
I leave it as I still believe it may be of use to someone.
Please take it with a gain of salt, I apologize for any headache called by the poorly laid out structure of the answer.
I Following this thought to guide the development object-oriented Perl.
Bless associate any data structure reference with a class. Given how Perl creates the inheritance structure (in a kind of tree) it is easy to take advantage of the object model to create Objects for composition.
For this association we called object, to develop always have in mind that the internal state of the object and class behaviours are separated. And you can bless/allow any data reference to use any package/class behaviours.
Since the package can understand "the emotional" state of the object.
For example, if you can be confident that any Bug object is going to be a blessed hash, you can (finally!) fill in the missing code in the Bug::print_me method:
package Bug;
sub print_me
{
my ($self) = #_;
print "ID: $self->{id}\n";
print "$self->{descr}\n";
print "(Note: problem is fatal)\n" if $self->{type} eq "fatal";
}
Now, whenever the print_me method is called via a reference to any hash that's been blessed into the Bug class, the $self variable extracts the reference that was passed as the first argument and then the print statements access the various entries of the blessed hash.