Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Object Constructors - Advice of experienced OO Perl Monks

by ghenry (Vicar)
on Oct 06, 2005 at 11:41 UTC ( #497888=perlquestion: print w/replies, xml ) Need Help??
ghenry has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

Quick one - "Are there any limits on what you can/can't or should/shouldn't put into a constructor?"

(Updated with an example)
For example:

perltoot has:
sub new { my $class = shift; my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless ($self, $class); return $self; }

And WWW::Mechanize has:

sub new { my $class = shift; my %parent_parms = ( agent => "WWW-Mechanize/$VERSION", cookie_jar => {}, ); my %mech_parms = ( autocheck => 0, onwarn => \&WWW::Mechanize::_warn, onerror => \&WWW::Mechanize::_die, quiet => 0, stack_depth => 0, headers => {}, ); my %passed_parms = @_; # Keep the mech-specific parms before creating the object. while ( my($key,$value) = each %passed_parms ) { if ( exists $mech_parms{$key} ) { $mech_parms{$key} = $value; } else { $parent_parms{$key} = $value; } } my $self = $class->SUPER::new( %parent_parms ); bless $self, $class; # Use the mech parms now that we have a mech object. for my $parm ( keys %mech_parms ) { $self->{$parm} = $mech_parms{$parm}; } $self->{page_stack} = []; $self->env_proxy(); # libwww-perl 5.800 (and before, I assume) has a problem where # $ua->{proxy} can be undef and clone() doesn't handle it. $self->{proxy} = {} unless defined $self->{proxy}; push( @{$self->requests_redirectable}, 'POST' ); $self->_reset_page; return $self; }


Walking the road to enlightenment... I found a penguin and a camel on the way.....
Fancy a Just ask!!!

Replies are listed 'Best First'.
Re: Object Constructors - Advice of experienced OO Perl Monks
by izut (Chaplain) on Oct 06, 2005 at 11:52 UTC

    The class constructor is used to initialize the object, safely and completely, and can also be used to instantiate any compound objects you need to couple in your object. Besides that, I don't see anything you can't do on a constructor.

    Update: After seeing your update, the difference from perltoot and WWW::Mechanize::new was the way its doing things. There are not a default idiom to construct your objects. You can do the way you feel comfortable to.

    Igor S. Lopes - izut
    surrender to perl. your code, your rules.
Re: Object Constructors - Advice of experienced OO Perl Monks
by Perl Mouse (Chaplain) on Oct 06, 2005 at 12:20 UTC
    IMO, constructors should only construct the object, and not initiate them. If you do so, multiple inheritance becomes even more a pain than it already is.

    Suppose for instance there are two classes which you didn't write yourself (get them from CPAN, from a coworker, elsewhere). Both of them initiate the object returned from the constructor in the constructor themselves. Perhaps one of the classes uses a blessed hashref as object, the other the inside-out objects from Damians book. If the classes don't initiate the object in the constructor, MI is possible. If they do, MI is either impossible, or it's going to be hard.

    Perl --((8:>*

      What's MI?

      Btw, I can't see why you can't initialize your own object from constructor. One of the definitions I found about this is: "A constructor is responsible for preparing the object for action, and in particular establishing initial values for all its data, i.e. its data members. Although it plays a special role, the constructor is just another member function, and in particular can be passed information via its argument list that can be used to initialise it" (here).

      Igor S. Lopes - izut
      surrender to perl. your code, your rules.

        MI == multiple inheritance

        What he is basically saying is instead of having something like:

        sub new { my ($class, %args) = @_; my $self = bless( {}, $class ); foreach my $k ( keys(%args) ) { $self{$k} = $args{$k}; } return( $self ); }

        do something like:

        sub new { my ($class, %args) = @_; my $self = bless( {}, $class ); $self->init(%args); return( $self ); } sub init { my ($self, %args) = @_; foreach my $k ( keys(%args) ) { $$self{$k} = $args{$k}; } # anyother initialization here }

        This makes a clean separation between the construction and the initialization with no real downside.

        Frank Wiles <>

Re: Object Constructors - Advice of experienced OO Perl Monks
by phaylon (Curate) on Oct 06, 2005 at 12:29 UTC
    I mostly have the same constructor, if I need to initialize (or check something in the environment) I mostly use an _init() method called by the constructor.

    Ordinary morality is for ordinary people. -- Aleister Crowley
Re: Object Constructors - Advice of experienced OO Perl Monks
by jeffa (Bishop) on Oct 06, 2005 at 17:53 UTC

    To answer your initial question -- that depends on what you are trying to solve. :) You need to be more specific to get a answer with more value than that. You need to think in terms of readability, maintainabilty, correctness, robustness, etc.

    Here is a constructor i like use when the situation is quick and dirty

    sub new { bless {}, shift }
    That's all you need -- you can add attributes later. However, if i am writing production code, i might opt for the more verbose version:
    sub new { my $class = shift; my $self = { foo => 'bar', baz => 'qux', }; return bless $self, $class; }

    I try to use Class::MethodMaker whenever i can, i just like that module. Here is an example where i use that module to turn XML into real objects: XML::Simple + Class::MethodMaker. Hope this helps. :)


    (the triplet paradiddle with high-hat)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://497888]
Approved by marto
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2017-01-24 03:15 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (200 votes). Check out past polls.