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

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question: (object-oriented programming)

How do I make a constructor?

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I make a constructor?
by merlyn (Sage) on Apr 26, 2000 at 00:51 UTC
    The use of
      $class = ref($class) || $class;
    
    is unneeded 90% of the time, and insufficient for 90% of the rest of the time.

    If you want a clone method, use a clone or copy method on an instance. If you want another object of the same class as the first object, use

      my $two = ref($one)->new(@parms);
    
    Which reduces our canonical simple constructor to:
      sub new {
        my $class = shift;
        my $self = { @_ };
        bless $self, $class;
    
    Nice and simple.
Re: How do I make a constructor?
by chromatic (Archbishop) on Apr 20, 2000 at 20:35 UTC
    Simply create a subroutine that initializes something, blesses a reference to it into the appropriate class, and returns the blessed reference. There is no enforced naming scheme (as there is in C++ or Java, for example), but many Perl hackers use new:
    sub new { my $class = shift; # allow for inheritance $class = ref($class) || $class; # allow indirect or # direct calling my $self = {}; # create an anonymous # array to hold member data bless($self, $class); # allow for inheritance return $self; # return new object }
    That's the canonical constructor. It takes the name of the class into which to bless the object (provided automatically), discerns the proper name (whether it is called through an instance of that class or indirect means), creates an anonymous hash for member data, uses the dual-argument form of bless to be sure that the object is created as a type of the desired (not just the current) class, and provides it to the caller in a nicely wrapped package.

    You will probably want to be in your own package before you declare this constructor, though.

Re: How do I make a constructor?
by jamesduncan (Novice) on Apr 08, 2003 at 11:34 UTC
    I tend to use:
    sub new { my $class = shift; my $self = {}; if (bless( $self, $class)->init( @_ )) { return $self; } else { # throw some sort of error } } sub init { 1; }
    That way all subclasses can initialize themselves in a standard way with something along the lines of:
    sub init { my $self = shift; if ($self->SUPER::init( @_ )) { ## do some sort of initialization ## or return false return 1; } else { return 0; } }
    and I'll know if something goes wrong...
      I'd be inclined to write that as follows:
      sub new { return (bless {}, shift)->init(@_); } sub init { my $self = shift; $self->SUPER::init(@_); 1 # put stuff to initialize here or die "Failed to init $self: blah blah\n"; return $self; }

      Makeshifts last the longest.

Re: How do I make a constructor?
by jdhedden (Deacon) on Jul 05, 2005 at 19:49 UTC
    I'm a pragmatist, and see nothing wrong with supporting $obj->new(). In fact, perlobj even mentions it. If your class takes args that are in addition to what the parent class uses in ->new(), then you need a bit more code.
    # Create a new object sub new { my $thing = shift; my $class = ref($thing) || $thing; my $self = {}; bless($self, $class) if (! $self->_init($thing, @_)) { # Failed to initialize # Throw some sort of error, or return; # Returns 'undef' } return ($self); } # Initialize a new object sub _init { my $self = shift; my $thing = shift; # Separate '@_' into args for parent class and args for this sub +class my @parent_args = ...; my @my_args = ...; # Perform parent class initialization if (! $self->SUPER::_init($thing, @parent_args)) { # Parent class initialization failed return (0); } # Perform subclass initialization # Making use of '@my_args', if any if (ref($thing)) { # $thing->new( ... ) was called # Make use of '@my_args', if any # And make use of object's data, if applicable } else { # CLASS->new( ... ) was called # Make use of '@my_args', if any } return (1); }
    Note that $thing is passed to _init() in addition to the args (cf. jamesduncan's code above). When the user calls $obj->new(), this allows the initialization method to make use of data contained in the calling object, if that is applicable to your code.

      Why the separate _init method?

      the lowliest monk

        I do this same thing with the _init(). Basically I can use an inheritence and the constructor remains the same, the _init method can change with each child object. It just seems to keep things organized.

        Don
        WHITEPAGES.COM | INC

        Edit by castaway: Closed small tag in signature

Re: How do I make a constructor?
by SoftTerrier (Initiate) on Dec 05, 2002 at 18:49 UTC
    Don't call your contructors explicitly throughout the code. Use Class Factory instead.