Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^4: Perl "new" command

by JavaFan (Canon)
on Mar 01, 2012 at 10:28 UTC ( [id://957152]=note: print w/replies, xml ) Need Help??


in reply to Re^3: Perl "new" command
in thread Perl "new" command

That would be a silly and confusing definition. If you had:
sub foo { my $x = bless [], "X"; my $y = bless {}, "Y"; ... return 1; }
Is that a double constructor? Half a constructor?

Replies are listed 'Best First'.
Re^5: Perl "new" command
by salva (Canon) on Mar 01, 2012 at 12:18 UTC
    bless attaches a method dispatch table to some Perl data structure. That's not what most people would consider a constructor.

    In most programming languages the constructor is some function that gets called once the object has been allocated in memory in order to have its attributes initialized. Setting its method dispatching table is something done by the language runtime under the hood, not inside the constructor.

    Perl leaves to the programmer the task of allocating the object storage, setting the dispatch table and initializing the object for greater flexibility.

    In my opinion, a constructor in Perl can be any function or code fragment returning a new object in an usable state. For some simple cases, just a bless {}, $class can qualify as such, but the usual thing is to use a method for that and to call it "new".

      Perl leaves to the programmer the task of allocating the object storage, setting the dispatch table and initializing the object for greater flexibility.
      In theory.

      In practice, the overwhelming majority of the programmers screws this up, each and every time they create a class. I bet there are seasoned Perl programmers who haven't managed not not screw up.

      Consider:

      package Colour; sub new {bless {colour => $_[1]}, $_[0]} sub colour {$_[0]{colour}} package Age; sub new {bless {age => $_[1]}, $_[0]}} sub age {$_[0]{age}}
      Whee. Now I can make colour objects, and age objects:
      use Colour; use Age; my $c_obj = Colour::->new("orange"); my $a_obj = Age::->new(42); print "I have an object with colour ", $c_obj->colour; print "And another object aged ", $a_obj->age;
      Goodie. Now, if there was any flexibility, I'd be able to create a class that's both, using multiple inheritance, and without breaking encapsulation (that is, peeking and making use of the implementation of a parent class):
      package Age_and_Colour; use Age; use Colour; our @ISA = qw[Age Colour]; sub new { my ($class, $age, $colour) = @_: ... Now what? ... }
      If I call Age::->new, I get back an object initialized with an age, but no colour; but if I call Colour::->new, I get one with a colour, but no age.

      Greater flexibility is fine, but if this requires a lot more effort from the programmer, it's pointless. That's like saying C has greater flexibility when it comes to regular expressions: it gives you a minimal string implementation, and leaves everything else to the programmer. Sure, you *can* make more fantastic regular expressions in C than in Perl, but I don't see many people actually doing that.

      (cue the Pavlov reactions: "but you shouldn't use MI anyway")

        ... Now what? ...

        can be replaced by:

        bless do { my %self = (%{Colour->new($colour)}, %{Age->new($age)}); \% +self }, $class;

        Moose (and some of its imitators) thankfully handles all of this for you. The Moose philosophy is to never write your own new method - rely on Moose to take care of it for you. If you do need to do some initialisation, then create a BUILD method - no matter how complex the inheritance you're using, Moose should call all the BUILD methods in a sane order.

        The other solution is to go the inside-out object route. If your class doesn't care about the contents of the reference, then all is fine and dandy. The reference doesn't even have to be a hash/array any more - it could be a scalarref, a coderef, a quoted regexp, etc. Inside-out objects have been traditionally fiddly to write without leaking memory, but the recent "fieldhashes" modules have made it a lot easier.

Re^5: Perl "new" command
by nemesdani (Friar) on Mar 01, 2012 at 12:42 UTC
    Well, if I had to, I'd name it a multiple constructor. I would find it a "silly and confusing" way to do things ;). I read that definition in the Perl documentation by the way.
      So, a subroutine that creates a couple of objects, none of which survive the life time of said subroutine, and which returns an integer, is a "multiple constructor", but it's also "silly and confusing"?

      I find both your classifications of the subroutine not very useful.

        1. I just stated originally, that there is no built in new function in Perl.
        2. I totally agree with you, that Perl's approach is very dangerous, but it doesn't change the fact, that - by the documentation I read - a constructor is simply a sub, that returns a blessed reference.
        If not so, please point me towards the correct documentation, I am not a seasoned Perl veteran.
        A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://957152]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-03-19 09:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found