I don't understand why a Perl constructor needs all this blessing, and why it is always done with a hash (it is possible to use other variable types, apparently).
How does it make any sense that a constructor would return a blessed reference to a hash when I create a new instance of a class? I could understand "return (this);" or something along those lines, but returning some other random variable just mystifies me (particularly when you are supposed to use a hash).
my ?var = new Test("foo");
package Test;
our $localvar;
sub new{
localvar = $_[1];
}
OK, so I have this basic class. I can set a class variable when I initialize it and then later use it like $var::localvar. But to have this actually compile and work in Perl I need to add in the line "return bless {}, shift;"???
It seems that this hash is sort of used as the instance of that class, with the methods being rather static. But you can still have class variables. It sounds like you are just linking a data object to a list of methods that take that object as a argument. But I am not sure why every tutorial would imply that you always use a hash if that was all that was happening. And I am confused why you have both this hash and any "our"s you declared in the class, they seem like mutually exclusive concepts?
It sounds like you are just linking a data object to a list of methods that take that object as a argument.
That's exactly what OO is, yes. The thing you return from the constructor is the instance. Unlike some other languages where the language creates a new "object instance" behind the scenes, and your constructor is just in charge of filling in slots, in Perl your constructor method gets to do the entire job. {} creates a reference to a new anonymous hash which will become the storage for the object, and bless is what actually turns that reference into an object, by tagging it with your class name.
But I am not sure why every tutorial would imply that you always use a hash if that was all that was happening.
A class can be any kind of reference, but a hash reference is the most useful and convenient, because hashes have named slots, so you can refer to your object's properties by name. There are examples out there of globref objects (filehandles and sockets), arrayref objects (rare, usually used for objects with only a few fields when the author is very concerned about speed and memory usage), and scalarref objects (often used to encapsulate a pointer returned by some C library). But hashref objects are "standard".
I can set a class variable when I initialize it and then later use it like ?var::localvar.
But why would you? Class variables are almost entirely useless, and there's no reason to bother with them until you have a grasp on more basic, and useful things.
How does it make any sense that a constructor would return a blessed reference to a hash when I create a new instance of a class?
Well, it would be a rather useless constructor if you didn't return the object you've created.
I could understand "return (this);" or something along those lines
Then what's the confusion? That's exactly what you should be returning. (Except the convention is to call it $self.)
sub new {
my ($class, ...) = #_;
my $self = bless({}, $class); # Or: my $self = $class->SUPER::new(...);
$self->{attribute1} = ...;
$self->{attribute2} = ...;
return $self;
}
It seems that this hash is sort of used as the instance of that class,
The blessed hash is the instance of that class aka the object.
Questions from the comments
Why do I have to [do my $self = bless({}, $class);] instead of just referencing the class instance. Like: $self = bless($class)
{} allocates a variable and bless associates it with a class. Two necessary steps in the creation of an object.
By having the two separate, you have the option of using different base variables for your object. For example, IO::Socket::INET uses a glob instead of a hash.
But most objects anyone would make would have no use for a hash in my opinion. A hash is a pretty specific data structure that is not needed or helpful for 99% of coding.
The point isn't to use a hash table; it's to use an associative array (where each element is an attribute).
Associative arrays (hash tables or otherwise) are both "needed and helpful" in far far more than 1% of coding.
Related
I am currently working on a Perl 5.8 project.
I have package that looks like:
package Foo::Bar;
use strict;
use warnings;
use Class::Std;
our #EXPORT_SAFE = qw(Class::Std);
my %baz :ATTR;
sub BUILD {
my ($self, $ident, $args) = #_;
$baz{$ident} = $$args{something};
}
I am not exposing baz with any getter, but I would like to fetch it's content for unit testing purposes. There is any way to do it in Perl?
e.g. in Ruby you can some_instance.instance_variable_get("##{name}")
Thank you very much in advance
TL;DR
The answer in the general case is "it depends (but probably)".
The answer in your case is "no".
Detail
There is no fixed way to implement classes and objects in Perl. In most cases an object will be a blessed reference to a hash. In those cases, you could simply treat the object reference as a hash reference and look up the key directly. So, code like this:
my $baz = $obj->{baz};
However, you're not using the most common approach to building Perl objects, you're using Class::Std. And Class::Std does things rather differently. Class::Std uses an approach called "inside-out objects" which was popularised by Damian Conway in Object Oriented Perl and which was very fashionable for a while about twenty years ago.
In normal objects, you have a hash for each object. The keys are the attribute names and the values are the attribute values. With inside-out objects, each attribute has its own hash. The keys are the stringified references to an individual object and the value is the attribute's value for that object.
In effect, the "standard" approach is:
$object{attr} = value;
And the inside out approach is:
$attr{object} = value;
One of the big reasons why people liked inside-out objects is that the attribute hashes can be lexical variables stored in the class's source code. And that means they are truly private and cannot be accessed from outside of the class - except by using the provided accessor methods. Which is great if you want to force Perl to implement a far stronger kind of encapsulation. But terrible if you want to break through that encapsulation in the way that you do here.
So, no. In your case, you can't do this.
Class::Std could easily provide ->instance_variable_get, at least for variables that were given a name.[1] But it doesn't.
In the absence of something provided by Class::Std, you could add the following to your class:
use Carp qw( croak );
sub instance_variable_get {
my ($self, $name) = #_;
my $pkg_glob = do {
no strict qw( refs );
*{ __PACKAGE__ . "::" }
};
exists($pkg_glob->{$name})
or croak("Unknown attribute $name");
my $hash = *{ $pkg_glob->{$name} }{HASH}
or croak("Unknown attribute $name");
return $hash->{ident($self)};
}
Note that this requires using our instead of my for the hashes.
This will allow you to use
$some_instance->instance_variable_get('baz')
Of course, if you're using our for the hashes, you could also use
$Foo::Bar::baz{ $some_instance->ident }
Currently, :ATTR( :name<...> ), :ATTR( :init_arg<...> ), :ATTR( :get<...> ) and :ATTR( :set<...> ) provide a name for the attribute, though these all have other effects as well.
In Perl, it's easy to bless a hashref and use it to store and read properties:
package MyPackage;
use strict;
use warnings;
sub new {
bless {}, __PACKAGE__;
}
sub SomeProperty {
my $self = shift;
if (#_) {
return $self->{SomeProperty} = shift;
}
$self->{SomeProperty};
}
# Or even like this to be able to call $obj->OtherProperty = $x;
sub OtherProperty : lvalue {
my $self = shift;
$self->{OtherProperty};
}
But, I've seen some Classes (from different Perl modules) that, when dumped, show a simple scalar blessed:
$obj = bless( \$8756489, 'Some::Package' );
Yet, they have methods and properties. The methods I understand, any subroutine a package can call then will be called when asking a blessed $object->name. The part I'm not understanding is how they can store properties. Where are those properties being stored?
Several times they accept things like $obj->property = $x or $obj->property($x) and can be independent of other instances of the same Class. Where are those properties being stored?
I know that really depends on the underlying implementation of the Class, what it is doing or what it is interacting with, and that can actually answer the question several times (e.g. the object is just interfacing with another object or connection somewhere and only sending or quering values to it).
However, if there's a way for a scalar based object to store properties (like in a different concept or approach to class structure in Perl), I'd really like to know it.
Thanks in advance for any comments! :-)
Well, one way is to use inside-out objects. Another is to use an XS-based class, where the scalar stores the address of a C/C++ structure in which the properties are stored (this is normally done only when the class's purpose is to interface with a C/C++ library).
You could also do something weird like index parts of the scalar using substr or pack, but I doubt anybody's done that except to prove it could be done.
I read the "Programming Perl" book which is rather complicated in some places. And one of those places is the section "Instance Destructors" in the 12th chapter "Objects". This section says:
Objects in Perl are destroyed when there is no more references to them.
There is an opportunity to capture control just before object is going to be recycled by defining DESTROY method in its class.
Although destructors are rarely needed in Perl, some objects may have, for instance, filehandles or database connections, which are outside of the memory system. So it is necessary to attend them specially.
Perl does not do hierarchical destruction.
Then there is a paragraph which I failed to understand:
This only applies to inherited classes; an object that is simply contained within
the current object—as, for example, one value in a larger hash—will be freed
and destroyed automatically. This is one reason why containership via mere ag-
gregation (sometimes called a “has-a” relationship) is often cleaner and clearer
than inheritance (an “is-a” relationship).
I can't understand what it means. Does it mean that an object that IS NOT simply contained within the current object, WILL NOT be freed and destroyed automatically?
I do know that a DESTROY that is called on the garbage collection is the nearest one and only one. No other overridden DESTROY methods are called when there is no refs to an instance. But, as I understand, the same behavior is expected when a ref to an instance is placed inside another object.
Would someone be so pleasant to construe and to provide a code-example ?
UPDATE:
Actually what I was looking for, was the explanation of the This only applies to inherited classes; words which turned out to be that:
If you have an instance of a class and it has a DESTROY method than that method will override DESTROY methods of a parent class(es), but that does not apply to an object, that is in a has-a relationship with the object in question. Its DESTROY won't be overridden
Sorry for not clear question, it would better fit to the English Language and Usage. Thanks to everyone.
Rule 1: Objects in Perl are destroyed when there is no more references to them.
{
my $object = Class->new()
}
# there are no more references to $object
# (it is out of scope and can't be accessed by any means)
# Perl is free to garbage-collect it.
Rule 2: There is an opportunity to capture control just before object is going to be recycled by defining DESTROY method in its class.
package Class;
sub new { return bless({}, shift) }
sub DESTROY { print STDERR "The object is destroyed" }
####
{
my $object = Class->new();
}
# before the object is garbage-collected, cleanup-operations should be manually performed
# like closing down connections, solving circular references
# any time, the object might print it's message.
Rule 4: Perl does not do hierarchical destruction.
package AnotherClass;
use Class;
use parent 'Class';
sub DESTROY { print STDERR "subclass reporting dead" }
Now if AnotherClass will be instantiated, only the DESTROY method of AnotherClass will be called, not the DESTROY method of Class. This is meant with the absence of a hierarchical destruction. This is obvious, as the DESTROY method overwrites the previous entry. The original DESTROY can be called manually
Using a parent class and a child class is a IS-A relationship: AnotherClass is a Class.
If we have YetAnotherClass:
package YetAnotherClass;
use Class;
sub new {return bless({member => Class->new()}, shift) }
{
my $object = YetAnotherClass->new();
}
# $object goes out of scope (zero reference count) and will be destroyed.
# Therefore, the reference count of the "member" drops to zero
# The member will therefore be destroyed and print it's message.
This is a case of aggregation (Class is a data member of YetAnotherClass), and a HAS-A relationship.
In a has-a relationship, the object often has a reference to the other object. Thus given the class Van, an instance of a Van has wheels. When that instance is destroyed, perl (the program) will call the destructor for Wheel objects separately, because they are two distinct objects.
In an is-a relationship, the reference for Van IS the same reference for the Vehicle object in question. Thus it does not, as some languages do, step through the hierarchy calling DESTROY on all the inherited classes, it simply calls DESTROY once for each blessed reference.
NOTE: #1 is not always the case. For example inside-out objects do not contain references to subclasses, they are blessed scalar references whose addresses are used as a key into a lexical hash in the package. The lexical scope of the persistent package holds the reference, not the object. But this just serves to make it no direct correlation between class clean-ups and is-a/has-a relationships.
It is still clear that a separate destruction would need to be made, even despite that perl does not automatically reap these has-a relationships.
So I think the key to understanding this is that in has-a relationships, there is a separate reference which needs to be destroyed. Perl either does it automatically as a reference count is decremented, or you have to do this yourself.
A has-a relationship is one in which an object simply stores another type of object. Just like an object can store a number or string, it can also store another object. It's really no more complicated than that.
package MyClass;
sub new {
my $class = shift;
my $obj = bless {}, $class;
$obj->{some_thing_else} = SomeOtherClass->new;
}
An is-a relationship is another name for inheritance.
package SomeSubClass;
use parent 'SomeParentClass';
# older ways to do this are 'use base' and pushing on #ISA.
There's nothing particular about those concepts as it pertains to Perl, but I have shown Perl examples above.
Your first example is just a standard Perl class. Your second example is a has-a relationship. Neither of your code snippts an example of inheritance (is-a).
[By the way, when calling bless in your method new, you should get the class name from the first parameter of new (as I have shown above), otherwise, people will not be able to inherit from your class without overriding new. If I call SomeSubClass->new, and SomeSubClass has inherited new from SomeParentClass, and SomeParentClass does what you just did, then I will get an object of the class SomeParentClass instead of SomeSubClass. (Of course, maybe you don't want your class to be inheritable, or you want new to be overridden, for whatever reason.)]
Perl's object system is very bare bones, you can make anything you want of it. But the community is moving toward something called Moose, a CPAN module which offers a more sophisticated object system built on top.
Inheritance is a a relationship of 'is-a' and any attribute the class / package have (moose with 'has') or hash keys of the blessed object (assuming the object is blessed into an hashref for instance) is a has-a
I define a method inside a parametrized role that needs to create a new class at run time
using Moose::Meta::Class->create and apply that exact parametrized role to it. I am also making a new method for that role using
$new_class->meta->add_method( some_name => sub {
my ($self) = #_;
...
})
inside the sub {...} I want to access a method of the consumer class and use it for something, I have tried using $self->get_method, it didn't work, how do I do this?
Please notice that the $self inside the sub above is MooseX::Role::Parameterized::Meta::Role::Parameterizable
I also have another question, if I do this:
my $object = Moose::Meta::Class->create(
"some_type",
);
Why isn't $object of type some_type and it's some ugly MooseX::Role::Parameterized::Meta::Role::Parameterizable and how do I get to the object of type some_type?
To answer your second question, the reason is because Perl's OO doesn't allow you to add a method to just one instance of a class, so Moose has to fake it by creating a subclass with the extra method and reblessing the unique object into that subclass.
Note that, if you are doing things correctly and doing your introspection with isa, has, and/or does rather than by trying to rely on the name of the object's blessed package, this doesn't matter. The object still isa some_type, has all of some_type's attributes, and does all of some_type's roles even though it's now blessed into a package with an ugly auto-generated name.
It sounds like your underlying problem is nearly exactly what I described at this question: from within the role definition, you need to get at the class (and its meta-class) of the object or class the role is being applied to. This isn't possible from within normal roles, but it's possible through parameterized roles.
I'm not quite sure what you're trying to do here. Let's assume you have
my $new_class = Moose::Meta::Class->create('FooBar');
then $new_class is the meta object for FooBar. So, if you want to add a method to FooBar you would say
$new_class->add_method(foo => sub { … });
which would basically be the same as
FooBar->meta->add_method(foo => sub { … });
You should also probably use find_meta() from Moose::Util. This will return the correct meta object (if there is one) even if your class doesn't have a meta method or it uses it for something else.
As said, I'm not sure this answers your question.
I noticed that when you call a superclass's methods, you need to do something like this :
my $self = $class->SUPER::new();
Why isn't that:
my $self = $class->SUPER->new();
I suspect because $class->SUPER->new() would normally be the same as $class->SUPER()->new(). But there isn't a $class->SUPER() function, and its not clear what that would return.
On the other hand, $class->Foo::Bar has always been a valid way to call a method directly by full name, so making a special package-like thing — SUPER — fits in better. (I suspect that you could actually implement SUPER as a package, and maybe it historically was, I don't know)
PS: Take a look at the mro package, and $self->next::method. Also, take a look at Moose if you're going to do serious OO work in Perl.
In short, SUPER isn't a method. It's a virtual package. It's documented in perlobj under the "Method Invocation" section.
Note, however, that SUPER bases itself on the current package, not the package of the instance you used it with.
Method calls have a number of forms:
Calls method, possibly inherited:
->method()
Explicitly calls sub Package::method, whether that's in the inheritance tree or not:
->Package::method()
Explicitly calls the referred-to sub, whether that's in the inheritance tree or not:
->$coderef()
Calls the method that would have been called by __PACKAGE__->method() if there were no sub method in __PACKAGE__ (N.B. the class or object on the left of -> is irrelevant):
->SUPER::method()
Any of the above, depending on the contents of $method:
->$method()
(Legal even under use strict;.)
While the first form is the most common, it's worth learning about the others and how they work.
To add to what derobert said:
You're calling 'new' in the 'SUPER' namespace but passing it the object (or string), '$class'.
You don't have to use SUPER, as you can give the full package name of the parent (useful in cases of diamond inheritance):
sub init {
my $self = shift;
$self->ParentClass1::init();
$self->ParentClass2::init();
}