Perl has OOP features, but they are somewhat rarely used. How do you create and use Perl objects with methods and properties?
You should definitely take a look at Moose.
package Point;
use Moose; # automatically turns on strict and warnings
has 'x' => (is => 'rw', isa => 'Int');
has 'y' => (is => 'rw', isa => 'Int');
sub clear {
my $self = shift;
$self->x(0);
$self->y(0);
}
Moose gives you (among other things) a constructor, accessor methods, and type checking for free!
So in your code you can:
my $p = Point->new({x=>10 , y=>20}); # Free constructor
$p->x(15); # Free setter
print $p->x(); # Free getter
$p->clear();
$p->x(15.5); # FAILS! Free type check.
A good starting point is Moose::Manual and Moose::Cookbook
If you just need the basic stuff you can also use Mouse which is not as complete, but without most of the compile time penalty.
Moose, definitely.
package Person;
use Moose;
has age => ( isa => Int, is => 'rw');
has name => ( isa => Str, is => 'rw');
1;
Immediately, you have for free a new() method, and accessor methods for the attributes you just defined with 'has'. So, you can say:
my $person = Person->new();
$person->age(34);
$person->name('Mike');
print $person->name, "\n";
and so on. Not only that, but your accessor methods come type-checked for free (and you can define your own types as well as the standard ones). Plus you get 'extends' for subclassing, 'with' for roles/traits, and all manner of other great stuff that allows you to get on with the real job of writing good robust maintainable OO code.
TMTOWTDI, but this one works.
Currently I use Object::InsideOut whenever I want objects, its quite nice and will give you a lot of features over standard blessed hash objects. Having said that, if I was starting a new project I would seriously look at Moose.
While it is good to read the official PERL documentation, I would NOT recommend trying to role your own object framework, or building objects using hashes, its far to tempting to take the easy road and "peak" directly into the objects "private" variables completely breaking encapsulation, this will come back to bite you when you want to refactor the object.
Perl objects are NOT just blessed hashes. They are blessed REFERENCES. They can be (and most often are) blessed hash references, but they could just as easily be blessed scalar or array references.
The official tutorial on the CPAN site is good.
There's also a good article called Camel POOP at CodeProject.
I highly recommend taking a look at Moose if you want to do OO in Perl. However, it's not very useful if you don't understand what OO in Perl means. To better understand how Perl OO works under the hood, I wrote an overview on my blog: http://augustinalareina.wordpress.com/2010/06/06/an-introduction-to-object-oriented-perl/
From a data structure point of view, an Object is reference with a few extra features. The interpreter knows to treat these special references as Objects because they have been "blessed" with the keyword "bless". Blessed references contain a flag indicating they are an Object. Essentially this means you can define and call methods on them.
For instance if you created a basic hashref, this wouldn't work:
$hashref->foo();
But if you create a blessed hashref (aka an Object) this does work:
$blessed_hashref->foo();
Moose is an excellent module for OOP in Perl because it creates an enforceable OO layer AND automagically handles accessor methods so you don't have to define a bunch of getters and setters. If you're interested in using Devel::Peak to see how the Perl interpreter stores objects, follow the link to the blog entry I posted above.
On one foot, each class is a package; you establish (multiple, if desired) inheritance by setting the package variable #ISA (preferably at compile time); you create an object from an existing piece of data (often, but not always, an anonymous hash used to store instance variables) with bless(REFERENCE [, CLASSNAME]); you call object methods like $obj->methodname(#ARGS) and class methods like "CLASSNAME"->methodname(#ARGS).
Multiple inheritance method resolution order can be altered using mro.
Because this is somewhat minimalistic and doesn't force encapsulation, there are many different modules that provide more or different functionality.
Related
Premise
The question is difficult to understand, due to a misunderstanding of the OO logic in perl by me, the OP. The comments can be useful to understand it.
Original question
The Class::Accessor module is extremely convenient for me, but I can't find any documentation about how to write a constructor such that I can, for instance, derive the values for a field out of some computation.
The closest thing I can think of, with the given documentation, is passing trough a "sort of" override:
package FooHack;
...
use Class::Accessor 'antlers';
has something => ( is => 'ro' );
# Methods here...
package Foo; # Foo is a plain module, not a class.
sub new {
my $macguffin = &crunch_chop_summon;
FooHack->new({something => $macguffin });
}
This kinda works, except my $f = Foo->new(); say ref $f will yield FooHack instead of Foo.
So my questions are:
Is my idea good enough or do you see some possible issues with it? Or maybe some improvements?
Is there a better way of doing the same thing?
Edit:
This is NOT an actual override. Foo is nowhere a class. It's just a plain module declaring a sub new. Plus, the module FooHack is not an external module. It is defined within the very same file.
The module Foo pretends to be a class in that it follows the convention of having a sub new, while new is actually just a function which calls the real constructor, FooHack->new and passes some initialization value for it.
TL;DR use Moose instead of use Class::Accessor will help a lot, and you shouldn't have to change your has definitions
As I wrote in my comment, you are asking Class::Accessor — a module that easily creates accessor methods — to provide the full quorum of object-oriented features
I also think your thoughts about object-oriented inheritance are confused. I don't see anything wrong in what you have written, but having Foo as a subclass of FooHack is wrong thinking, and confused me as well as probably many others
There should be a Foo base class and potentially multiple subclasses, like FooHack, FooPlus, FooOnHorseback etc.
Well, it's a little bit nasty to tamper with a module like that - if it's not doing what you want, then normally you'd just write a new one.
You can take a class and extend it to make a new class - that's what you'd normally do if the class in question doesn't do what you need. Applying a hack to override the constructor is subverting the expectations of the class maintainer, and the road to brittle code, which is why you can't do it easily.
That said - normally as part of a constructor you'll call bless to instantiate the object into a class. By convention, this is done into the current class, using the new method. But there's no real reason you can't:
my $self = {};
bless ( $self, 'Foo' );
Just bear in mind that if your constructor doesn't do things this object is expecting to have happened, then you might break things.
I want to be able to instantiate a Moose based object add to it until I serialize it and then I want to make it unchangeable. How can/should I go about doing this?
I would make two classes and a common Role:
package Thing
use Moose::Role;
has some_attrib => (isa => 'AnotherThing');
### Behaviour (the important stuff) goes here
package ImmutableThing;
use Moose;
with 'Thing';
has +some_attrib => (is => 'ro');
sub finalize { shift }
package MutableThing
use Moose;
with 'Thing';
has +some_attrib => (is => 'rw');
sub finalize {
my $self = shift;
Thing->new({some_attrib => $self->some_attrib});
}
I'm not sure that having mutable and immutable forms of the same class is necessarily a good idea though. I tend to try and think about build time and operation time as two distinct phases with different interfaces.
I would be more inclined to write a Parameter Collector (I've capitalised it like it's a pattern, but I've not seen it in the literature) that has an interface optimised to gathering the info needed to create a Thing, and the Thing Itself, which is the object that's used by the rest of the program.
I don't know of (and can't easily find) any modules to do this on CPAN which is surprising but explains why you are asking :-)
A "before" modifier over all your attributes is the obvious way to go about it. I'm sure there's a suitable meta-programming way to get a list of all attribute accessors and apply the modifier, but I'd be tempted to explicitly list them all with a big comment.
Have you considered whether you have one class or two here (Thingy, LockedThingy)? Two classes would let you encapsulate the meta cleverness if you're that way inclined.
I frequently use Moose to make sure my data have suitable default values, like here:
package Bla;
use Moose;
has eins => is => 'ro', isa => 'Int';
has zwei => is => 'ro', isa => 'Int', default => 2;
no Moose; __PACKAGE__->meta->make_immutable;
package main;
use v5.10;
use Data::Dumper;
use URI;
my $bla = Bla->new( eins => 77 );
my $bl2 = Bla->new;
print Dumper $bla, $bl2;
say join "\t", %$bla;
say join "\t", %$bl2;
my $u = URI->new( 'http://www.example.com/ws' );
$u->query_form( %$bla );
say $u;
$u->query_form( %$bl2 );
say $u;
As long as that kind of data container doesn't have any reference members (hence no nesting), would you say it is okay, or recommendable, to just use the object hashtable as in %$object if you want to get at the raw data, let's say as initializer for serialization via URI->query_form or similar methods? Or is there a better way to achieve this that's built into Moose?
UPDATE
Looks like I've been leading people on the wrong tracks by dropping the little word serialization in the lines above, and in the title, and even in the tags. Note that I'm not interested in finding serializers. In my example, the URI module is the serializer. The question is how to get at the data to feed URI->query_form (or any other serializer I might try). So what I want to know is whether for a given Moose object $object it is okay to grab the data (keys and values, or, if you prefer, property names and values) by just dereferencing the object reference, as in %$object? This will work, if my experience hitherto collected is anything to go by, as long as the objects don't contain any reference values (like array references, other objects, etc) and - the thing I'm not sure about - Moose won't use the instance reference to store data of its own, like __MOOSE_WHATNOT => $funky_moose_addon. So might Moose use the instance reference to store some of its own data, or is that precluded by design?
UPDATE 2
To answer the question in the title:
No, it's not okay to use %$object to get at the data of a Moose object, even if it doesn't contain any reference values so you'd get a copy of the strings and numbers that make up the $object. It's not okay because it breaks encapsulation. It might even result in a runtime error because although the hash is the default data structure to form the base of a Moose object, there is no guarantee that it will always be a hash, and it might in fact be something else.
You should use MooseX::Storage instead, which will provide the object with a pack method.
As jira has said the canonical way would be to use MooseX::Storage. The problem with %$object is that while the default storage for a Moose object instance is a blessed hash, Moose makes no formal promises that this is always the case. MooseX::GlobRef, MooseX::NonMoose, MooseX::InsideOut for example all allow for alterative instance structures.
A package like MooseX::Storage uses the MOP to interrogate the instance meta-object and serialize the data structure properly. You can of course do this by hand by crawling the Moose::Meta::Class that is behind every Moose object, but honestly MooseX::Storage is well written and very stable at this point.
The standard usage would be:
package Class {
use Moose;
use MooseX::Storage;
with Storage();
...
}
my $o = Class->new(...)
my $u = URI->new( 'http://www.example.com/ws' );
$u->query_form( $o->pack );
Moose "native" way would be to use MooseX::Storage set of classes.
first post from a newbie-user. Every question I google seems to bring me here and I always get a great answer to what I'm looking for; so naturally this was my first stop when I began pondering the usage of blessing in Perl.
I've just gotten into Perl's OOP and just today read the post asking what bless does. I now understand that it references a scalar/hash/array to an object, 'attaching' it, if you will.
In most of the examples of classes I see in Perl, they don't seem to have properties like I'm used to seeing in other languages...
{ package Person;
my $property = "This is what I'm talking about :)";
sub new { ... }
...
}
So, I created a stupid class with a property to see what would happen. I gave the property the value 'NIL' right off the bat and then 'Not Nil!' in the constructor. Using a method LIST, I was able to print the property, and as I expected, it printed 'Not Nil!'
My question is, if properties work the same as I expected them to work (declared in the body) then why use bless at all? What is the added benefit of having that reference when you could simply create a scalar/hash/array as a property, or create whatever references you want as a property?
I hope I explained what I'm trying to ask well enough, very green with Perl :)
Well, that is not how you create classes in Perl.
Your $property variable is defined in package scope. Therefore, there will only one copy of it per class rather than each object having its own copy.
One might implement such a class using hash based objects the long and hard way as below:
#!/usr/bin/perl
package Person;
use strict; use warnings;
sub new {
my $class = shift;
my $self = {};
bless $self => $class;
my ($arg) = #_;
for my $property ( qw( message ) ) {
if ( exists $arg->{$property} ) {
$self->$property($arg->{$property});
}
}
return $self;
}
sub message {
my $self = shift;
return $self->{message} unless #_;
my ($msg) = #_;
$self->{message} = $msg;
}
package main;
my $person = Person->new({
message => "This is what I'm talking about :)"
});
print $person->message, "\n";
Now, this gets tedious fast. So, there are modules that help you deal with this as well as helping you define your classes in way that is safe for inheritance.
Class::Accessor is one such utility module.
For programs where startup time is not an issue, you should consider Moose. With Moose, you can write the above as:
#!/usr/bin/perl
package Person;
use Moose;
has 'message' => (is => 'rw', isa => 'Str');
__PACKAGE__->meta->make_immutable;
no Moose;
package main;
my $person = Person->new({
message => "This is what I'm talking about :)"
});
print $person->message, "\n";
You should read perldoc perltoot and Moose::Manual::Unsweetened for the standard way of doing things.
What you did with $property in this case is declared a variable in the "Person" package's scope. You change that inside (or outside using $Person::property) of the package, and any object that refers to it will see the updated variable, so it acts a lot like a "static attribute (Java)" without any real "private" scope. By convention, hidden things in Perl ("private" or "protected") are prefixed with an underscore, but of course this isn't enforced.
You don't actually make a new class, as you pointed out, with the "package" keyword; you can use "package" without OOP at all. That simply creates a separate "namespace".
The advantage of "blessing" a variable, almost always a hash reference from what I've seen, is that you can have methods, just like any other OOP language. Just remember to bless whatever you return in the new {} subroutine ("new" isn't actually a reserved word; just a convention). When you call a method on the "object" (a blessed data structure like a hashref), the first argument of the method is the data structure itself. So, if you have a hashref called $myobject, which is blessed to AwesomeClass, and you define a method in AwesomeClass called doSomethingAwesome, which needs to accept one variable, you would have to "shift" #_ (which is the argument list of the subroutine, or use $_[0]) to access the $myobject hashref. Python does something similar, and all languages pass the object reference to the method somehow. ("this" keyword in many, see also "thiscall" calling convention)
NB: I've seen lots Perl bashing in my time, which has only been a few years as a programmer. Perl is an awesome language that was made by a very smart linguist (Larry Wall) and has a fanatical following -- more fanatical at one time than Ruby, perhaps, but not as much as David Koresh). Perl does things very differently than lots of languages but if you look at code golf entries on this site and others, you can clearly see that much can be accomplished with very little Perl (no guarantees about code legibility, especially for newcomers!)
The value of bless'ing an object is getting to use the methods from a particular package.
package MyClass;
sub answer { my ($self)=#_; return $self->{foo} * 42; }
package main;
my $object1 = { foo => 1, bar => "\t" };
my $object2 = bless { foo => 2, bar => "\t" }, "MyClass";
$ref1 = ref $object1; # 'HASH'
$ref2 = ref $object2; # 'MyClass'
$answer1 = $object1->answer; # run time error
$answer2 = $object2->answer; # calls MyClass::answer, returns 2 * 42 = 84
Ugh... Sinan's answer is entirely too learned for my taste, at least past 12am :)
So I'll give a shorter and somewhat less Perly one, just for variety's sake.
Your question is not really about Perl as far as I can tell, and can be just as easily ased in another form: "Why bother using C++ and OOP in it when C already has structs?"
In other words, you seem to be asking what the point of using OOP paradigm is.
The answer is of course that it helps solving certain software engineering problems easier than pure procedural programming. Emphasis on certain - OOP is not a panacea for every problem, any more than ANY technique/approach/paradigm is.
Using OOP (in a form of packages as classes and blessed hashes as objects in Perl) allows you to enjoy the benefits of inheritance, polymorphism and other OOPyish mumbo-jumbo which you are probably already fairly familiar with from you non-Perl OOP experience.
Can you do 100% of what you'd have done with a blessed object with a pure data structure? Absolutely. Would 100% of it be just as easy/short/readable/maintainable code as you can achieve using objects? Most likely not, though it depends on how well your OOP code actually leverages the benefits that OOP provides (BTW, I have encountered supposedly OOP code (Perl and not) which wasn't really taking any advantage of OOP paradigm and could have been made easier to read and understand had it been stripped of its OOP chrome).
This may turn out to be an embarrassingly stupid question, but better than potentially creating embarrassingly stupid code. :-) This is an OO design question, really.
Let's say I have an object class 'Foos' that represents a set of dynamic configuration elements, which are obtained by querying a command on disk, 'mycrazyfoos -getconfig'. Let's say that there are two categories of behavior that I want 'Foos' objects to have:
Existing ones: one is, query ones that exist in the command output I just mentioned (/usr/bin/mycrazyfoos -getconfig`. Make modifications to existing ones via shelling out commands.
Create new ones that don't exist; new 'crazyfoos', using a complex set of /usr/bin/mycrazyfoos commands and parameters. Here I'm not really just querying, but actually running a bunch of system() commands. Affecting changes.
Here's my class structure:
Foos.pm
package Foos, which has a new($hashref->{name => 'myfooname',) constructor that takes a 'crazyfoo NAME' and then queries the existence of that NAME to see if it already exists (by shelling out and running the mycrazyfoos command above). If that crazyfoo already exists, return a Foos::Existing object. Any changes to this object requires shelling out, running commands and getting confirmation that everything ran okay.
If this is the way to go, then the new() constructor needs to have a test to see which subclass constructor to use (if that even makes sense in this context). Here are the subclasses:
Foos/Existing.pm
As mentioned above, this is for when a Foos object already exists.
Foos/Pending.pm
This is an object that will be created if, in the above, the 'crazyfoo NAME' doesn't actually exist. In this case, the new() constructor above will be checked for additional parameters, and it will go ahead and, when called using ->create() shell out using system() and create a new object... possibly returning an 'Existing' one...
OR
As I type this out, I am realizing it is perhaps it's better to have a single:
(an alternative arrangement)
Foos class, that has a
->new() that takes just a name
->create() that takes additional creation parameters
->delete(), ->change() and other params that affect ones that exist; that will have to just be checked dynamically.
So here we are, two main directions to go with this. I'm curious which would be the more intelligent way to go.
In general it's a mistake (design-wise, not syntax-wise) for the new method to return anything but a new object. If you want to sometimes return an existing object, call that method something else, e.g. new_from_cache().
I also find it odd that you're splitting up this functionality (constructing a new object, and returning an existing one) not just into separate namespaces, but also different objects. So in general, you're closer with your second approach, but you can still have the main constructor (new) handle a variety of arguments:
package Foos;
use strict;
use warnings;
sub new
{
my ($class, %args) = #_;
if ($args{name})
{
# handle the name => value option
}
if ($args{some_other_option})
{
# ...
}
my $this = {
# fill in any fields you need...
};
return bless $this, $class;
}
sub new_from_cache
{
my ($class, %args) = #_;
# check if the object already exists...
# if not, create a new object
return $class->new(%args);
}
Note: I don't want to complicate things while you're still learning, but you may also want to look at Moose, which takes care of a lot of the gory details of construction for you, and the definition of attributes and their accessors.
It is generally speaking a bad idea for a superclass to know about its subclasses, a principle which extends to construction.[1] If you need to decide at runtime what kind of object to create (and you do), create a fourth class to have just that job. This is one kind of "factory".
Having said that in answer to your nominal question, your problem as described does not seem to call for subclassing. In particular, you apparently are going to be treating the different classes of Foos differently depending on which concrete class they belong to. All you're really asking for is a unified way to instantiate two separate classes of objects.
So how's this suggestion[3]: Make Foos::Exists and Foos::Pending two separate and unrelated classes and provide (in Foos) a method that returns the appropriate one. Don't call it new; you're not making a new Foos.
If you want to unify the interfaces so that clients don't have to know which kind they're talking about, then we can talk subclassing (or better yet, delegation to a lazily-created and -updated Foos::Handle).
[1]: Explaining why this is true is a subject hefty enough for a book[2], but the short answer is that it creates a dependency cycle between the subclass (which depends on its superclass by definition) and the superclass (which is being made to depend on its subclass by a poor design decision).
[2]: Lakos, John. (1996). Large-scale C++ Software Design. Addison-Wesley.
[3]: Not a recommendation, since I can't get a good enough handle on your requirements to be sure I'm not shooting fish in a dark ocean.
It is also a factory pattern (bad in Perl) if the object's constructor will return an instance blessed into more than one package.
I would create something like this. If the names exists than is_created is set to 1, otherwise it is set to 0.. I would merge the ::Pending, and ::Existing together, and if the object isn't created just put that into the default for the _object, the check happens lazily. Also, Foo->delete() and Foo->change() will defer to the instance in _object.
package Foo;
use Moose;
has 'name' => ( is => 'ro', isa => 'Str', required => 1 );
has 'is_created' => (
is => 'ro'
, isa => 'Bool'
, init_arg => undef
, default => sub {
stuff_if_exists ? 1 : 0
}
);
has '_object' => (
isa => 'Object'
, is => 'ro'
, lazy => 1
, init_arg => undef
, default => sub {
my $self = shift;
$self->is_created
? Foo->new
: Bar->new
}
, handles => [qw/delete change/]
);
Interesting answers! I am digesting it as I try out different things in code.
Well, I have another variation of the same question -- the same question, mind you, just a different problem to the same class:subclass creation issue!
This time:
This code is an interface to a command line that has a number of different complex options. I told you about /usr/bin/mycrazyfoos before, right? Well, what if I told you that that binary changes based on versions, and sometimes it completely changes its underlying options. And that this class we're writing, it has to be able to account for all of these things. The goal (or perhaps idea) is to do: (perhaps called FROM the Foos class we were discussing above):
Foos::Commandline, which has as subclasses different versions of the underlying '/usr/bin/mycrazyfoos' command.
Example:
my $fcommandobj = new Foos::Commandline;
my #raw_output_list = $fcommandobj->getlist();
my $result_dance = $fcommandobj->dance();
where 'getlist' and 'dance' are version-dependent. I thought about doing this:
package Foos::Commandline;
new (
#Figure out some clever way to decide what version user has
# (automagically)
# And call appropriate subclass? Wait, you all are telling me this is bad OO:
# if v1.0.1 (new Foos::Commandline::v1.0.1.....
# else if v1.2 (new Foos::Commandline::v1.2....
#etc
}
then
package Foos::Commandline::v1.0.1;
sub getlist ( eval... system ("/usr/bin/mycrazyfoos", "-getlistbaby"
# etc etc
and (different .pm files, in subdir of Foos/Commandline)
package Foos::Commandline::v1.2;
sub getlist ( eval... system ("/usr/bin/mycrazyfoos", "-getlistohyeahrightheh"
#etc
Make sense? I expressed in code what I'd like to do, but it just doesn't feel right, particularly in light of what was discussed in the above responses. What DOES feel right is that there should be a generic interface / superclass to Commandline... and that different versions should be able to override it. Right? Would appreciate a suggestion or two on that. Gracias.