home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Perl CookbookPerl CookbookSearch this book

13.6. Cloning Constructors

13.6.2. Solution

Start your constructor like this:

my $proto  = shift;
my $class  = ref($proto) || $proto;
my $parent = ref($proto) && $proto;

The $class variable will contain the class to bless into, and the $parent variable will either be false, or else the object you're cloning.

13.6.3. Discussion

Sometimes you need another object of the same type as the current one. You could do this:

$ob1 = SomeClass->new( );
# later on
$ob2 = (ref $ob1)->new( );

but that's not very clear. It's clearer to have a single constructor that behaves correctly, regardless of whether its invocant is a class name or an existing object of that class. As a class method, it should return a new object with the default initialization. As an instance method, it should return a new object initialized from the object it was invoked on:

$ob1 = Widget->new( );
$ob2 = $ob1->new( );

Here's a version of new that takes this into consideration:

sub new {
    my $proto  = shift;
    my $class  = ref($proto) || $proto;
    my $parent = ref($proto) && $proto;

    my $self;
    # check whether we're shadowing a new from @ISA
    if (@ISA && $proto->SUPER::can("new") ) {
        $self = $proto->SUPER::new(@_);
    } else {
        $self = {  };
        bless ($self, $class);
    }

    $self->{PARENT}  = $parent;
    $self->{START}   = time( );   # init data fields
    $self->{AGE}     = 0;

    return $self;
}

Initializing doesn't have to mean simply copying values from the parent. If you're writing a linked list or binary tree class, your constructor can return a new object linked into the list or tree, when invoked as an instance method.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.