http://qs321.pair.com?node_id=755461

tamaguchi has asked for the wisdom of the Perl Monks concerning the following question:

I need to write some more complicated perl5 code and would like to learn some perl OO. I am familiar with the OO-concept from other languages.

If I would like to make an object that has one instance variable I can do it in this way accoring to the book "Learning Perl Objects, References & Modules" :
my $name = "Mr. Ed"; my $tv_horse = \$name; bless $tv_horse, "Horse";
However to make an object with two variables the book uses a hash..:
my $lost = bless { Name => "Bo", Color => "white" }, Sheep;
This is intresting becouse it could mean that I can not have an perl5-object with more then one instance variable without using a hash. So how do you do if you would like to make an object that contains arrays, hashes and different many different instance variables? If you really have to create a complex datastructure to store all this, and then bless it much of the benefits with using objects will disepear. So is it possible to bless many different variables, arrays and hashes to the same object or how do you do?

I also wonder if you know which state of development perl 6 is in? Is in possible to use for production even if has not officially been released yet or is it still to incomplete and full of bugs?

Replies are listed 'Best First'.
Re: Trying to understand Perl Objects
by jasonk (Parson) on Apr 04, 2009 at 17:35 UTC

    In general what people do is put all those other things into the hash...

    my $foo = bless( { name => 'Bo', color => 'white', complex_behaviors => [ { name => 'one' }, { name => 'two' }, { name => 'three' } ], }, 'Sheep' );

    www.jasonkohles.com
    We're not surrounded, we're in a target-rich environment!
Re: Trying to understand Perl Objects
by lostjimmy (Chaplain) on Apr 04, 2009 at 17:48 UTC
    ...much of the benefits with using objects will disepear.

    You're really not losing the benefits of OO just because you have to store the private data in a complex data structure. Some of the benefits of OO are data encapsulation and data hiding, inheritance and polymorphism, and simply being able to provide an interface to your data.

    To elaborate on what jasonk already said, you may be putting your data all in a hash, but typically your object will have accessors and mutators (getters and setters) which will hide that hash from the user of the object. So instead of the user doing something like $object->{private_array}[5], your class would probably provide an easier and more abstracted way of getting that item, such as $object->get_item(5). This also gives you the freedom to change the underlying data structure in the future without the interface changing.

Re: Trying to understand Perl Objects
by ELISHEVA (Prior) on Apr 04, 2009 at 17:53 UTC
    If you really have to create a complex datastructure to store all this, and then bless it much of the benefits with using objects will disepear.

    How so? People use objects for many reasons, but one of the most important is the ability to bundle together data and the methods that use that data. You can still closely bundle data and process when data is stored in a hash. Since any pure scalar or reference can be stored as a hash value, you can store any type of variable needed by your methods: strings, numbers, file handles, compiled regular expressions, code references, array references, hash references, and even references to other objects.

    I can not have an perl5-object with more then one instance variable without using a hash

    Not so. You can bless any reference, including an array reference. Some people prefer to construct their objects using blessed array references. They feel it makes the object a little more opaque - unlike hash keys there is nothing in an array to indicate which variable has which meaning, thus making it harder to bypass accessor methods to get at data. Personally, I prefer a blessed hash with a member for each variable I want to store, but to each his own.

    Best, beth

      Some people prefer to construct their objects using blessed array references. They feel it makes the object a little more opaque - unlike hash keys there is nothing in an array to indicate which variable has which meaning, thus making it harder to bypass accessor methods to get at data.
      Is this really a reason that people use blessed arrayrefs? I always thought that it was for speed. Every object that I've ever seen structured this way got at the entries of the arrays by using named constants as indices, which would remove any “benefit” of opacity.
      Some people prefer to construct their objects using blessed array references. They feel it makes the object a little more opaque - unlike hash keys there is nothing in an array to indicate which variable has which meaning, thus making it harder to bypass accessor methods to get at data.

      I have never heard this rationale before, but it smells of "Security through obscurity" rather then any real solid reasoning. The most widely used array-based OOP module I know of is POE and that choice was made very specifically because of performance. Of course this was like 1999 performance, so how applicable that still is on modern systems I don't know.

      -stvn

      When I used to roll my own OO, I would do this. I liked it because it (in combination with strictures) gave me compile time errors when I made a typo in a field name. With a similar error using a vanilla hash, you just keep getting undef or setting something that never gets read.

      I didn't consider it opaque. All the fields in the object are nicely listed at the top of the module in a constant/enum statement.

      I never roll my own OO anymore. Also, I realize now that low-level field access in enough places to make the above argument valid is probably a bad sign.

Re: Trying to understand Perl Objects
by morgon (Priest) on Apr 04, 2009 at 18:24 UTC
    In Perl a Class is just a namespace, methods are just subs and object are just references that are blessed into a particular namespace (references to anything really - if you really want to you can build objects by blessing a format-handle),

    If you are really interested in Perl-OO I can recommend Damian Conway's book "Object Oriented Perl" which explains all the mechanics and some more advances techniques such as inside-out classes.

    I think you should definitely understand the way Perl-OO works in principle and then move on to something like Moose that takes the tedium out of it.

      Thank you all for your answers. I understand it now. The problem with having the a complex datastructure is thatthe inormation in it will be more difficoult to access. Yes you can have methods but the methods will be more difficult to write compaired to if the information was in "normal" variables, arrays etc. I also wonder how you do to associate a object to another object? Should the object reference be added to the anonymous hash? How could that be done?
        Here an example for association:

        package Rider;
        sub new {
         my($pck, $name)=@_;
        
         return bless { name => $name }, $pck;
        }
        
        This is a Rider-class with a "name"-attribute, you can create new instances with Rider->new("John Wayne"). Now a horse with a rider:

        package Horse;
        sub new {
         my($pck, $horse_name, $rider_name)=@_;
        
         return bless { 
                       name => $horse_name,
                       rider => Rider->new($rider_name),
                      }, $pck;
        }
        
        

        You can create instances with Horse->new("Mr Ed", "John Wayne"). The created class will have a "rider"-attribute which is an instance (= blessed reference) of the rider-class.

        So yes you simply store the object-references in your underlying data-structure.

        And by the way: The reason I bless not directly into "Rider" and "Horse" namespaces but rather use the package-name that the constructor gets passed when called via e.g. Rider->new (you should NOT call it as Rider::new) is so that I can re-use the constructor in a derived class - read Damian's book if this is unclear.

        hth

        I also wonder how you do to associate a object to another object? Should the object reference be added to the anonymous hash?

        Not exactly sure what you mean by 'associate', but an object reference can be stored like any other reference (it's just a scalar), e.g. as values in a hash... from where you can then access the object whenever needed.

        The problem with having the a complex datastructure is thatthe inormation in it will be more difficoult to access. Yes you can have methods but the methods will be more difficult to write compaired to if the information was in "normal" variables, arrays etc.

        This is strange. The idea being that 20 variables out in the open are somehow easier to deal with than 20 inside a single point of contact (an object). It's within the realm of possibility that the first could be slightly easier to access than the second only if the design is global in nature and that's one of the great evils that objects, class instances, avoid.

        Probably you should step out of the theoretical discussions immediately and try to write some OO Perl to see where and how it goes. Or give a clearly defined, minimal, problem in a new SoPW post to see the kinds of options and approaches the monks can provide for a real problem.

Re: Trying to understand Perl Objects
by targetsmart (Curate) on Apr 05, 2009 at 01:01 UTC
    Some where I have read this 'perl code with object oriented-ness will run 40% slower that without oo', IMO perl tries to give you the OO facility by doing some workaround, but to the core it is not purely object oriented. I have read this 'Object oriented perl' book, it is good place to start knowing about perl OO. The OO in perl will help you in making reusable, scalable and maintainable code.
    It is an appreciate-able thing that in Perl you can do both functional and object oriented programming.

    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.

      Well, I remembered that, as I read your post, and did a little research.

      Conway mentions the speed thing in his book Object Oriented Perl (as you already mentioned).

      Luckily Manning Publications has the preface of that book online, so let's quote from there:

      Quoted from section "What object-oriented Perl isn't"

      Because Perl wasn't originally designed as an object-oriented language, object-oriented Perl isn't fast. Calling a method through an object is significantly slower than calling a regular Perl subroutine. Just how much slower is a matter of some debate, and depends on whether you measure entire software systems or just raw single-call invocation speed.

      A single method call is about 30 percent slower than a regular call to the same subroutine (depending on your hardware, your operating system, the phase of the moon, etc.) But though they're individually much slower, method calls are more powerful than regular subroutine calls, due to a feature known as polymorphism (see chapters 1 and 7). In a larger system, that redresses the speed imbalance in a little, but, in general, it's fair to say that an object-oriented implementation of a system in Perl will almost never be faster than the equivalent non-object-oriented implementation, and will usually be somewhere between 20 to 50 percent slower.

      ...

      The sad thing is that people get spooked by the numbers (20 to 50 percent slower!!!) and forget what that really means (...just as fast in six months time, when processor speeds have doubled).

      I never did some benchmarking on my own to determine how much slower OO Perl is on my machines. I trust Conway in this matter and try to enjoy the benefit of OO (as I'm learning OO) ;o)

      The problem is that calling a method via $object->method always means Perl has do a lookup of the sub to be invoked via the namespace (and possibly walking up the @ISA-chain).

      This of course is not free - but do you really want to write large applications in a purely imperative way? (functional by the way programming is something else - think Lisp or Haskell for that).

Re: Trying to understand Perl Objects
by TGI (Parson) on Apr 06, 2009 at 21:03 UTC

    OOP in Perl has a very strong DIY flavor. As a result, there are all sorts of ways to build your objects in Perl: classical methods with blessed hash or array refs, inside out objects, and even more exotic XS based objects.

    You can do all the work yourself each time you write a new OOP module and implement all your accessors and mutators, type validation, and so forth manually. Or you can use one of the many modules to help automate the process.

    I have found that two ways of generating object code work well for me.

    For dirt simple objects that are used to contain some data and bind a few methods to the data structure, Class::Struct does a very nice job. It is very limited and somewhat brain-dead (eg. can't use it in subclasses), but for very, very simple tasks, it reduces a lot of busy-work, and I can understand exactly what it does.

    For anything with more than the most minimal demands, Moose is the way to go. It provides much of the goodness we will see with Perl6 objects. I've used it for a few projects now, and it is really quite amazing.

    For an example of why Moose is so great see the Moose Unsweetened document for a comparison of manual and Moose object code.

    Perl 6 is not even fully specified, and is certainly not ready for prime time. The Parrot VM just released version 1.0 which provides a stable API for language implementors, but is still not 100% ready for production use--that will come in 2.0. Both projects are cruising along, but both are far from being ready for production use. If you want perl 6 oo, with roles and type checking, etc. Moose is the best way to get it now.


    TGI says moo

Re: Trying to understand Perl Objects
by sundialsvc4 (Abbot) on Apr 07, 2009 at 12:28 UTC

    The key thing to recognize about “Perl objects” is that they are “other” data-structures ... usually hashes ... but they have had an epiphany. They are data structures that have been blessed, which is simply an attribute that Perl can recognize.

    When a data-structure has been “blessed,” Perl knows how to associate it with a particular package. Method calls therefore succeed, and they are resolved by looking up the package (and thence following the @ISA list).

    That's it.

    As for “the speed issue,” I am frankly of the opinion that:   at 500 million operations per second (or considerably more...) no one can hear you scream. The speed and reliability with which you can write the code, and with which it subsequently runs, trumps other petty-concerns in nearly evey practical case. If your application cannot tolerate the overhead of method-lookups, etc., then you should use another language for at least this part of it. However, you should refrain from judgment on this matter until you have actual benchmarks. You may be pleasantly surprised.

      The funny part to the speed thing is that a lot of these same alarmed folks will then go to java, which IMO truly shows the expense of going all-out on object oriented programming. OO for everything is not appropriate, and whomever started that rumor should be president of marketing somewhere.