You want to write a constructor method that might be called on an existing object.
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.
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 can be called on the class or an existing object. 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 called 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, $proto);
}
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 called as an instance method.
perlobj (1) and Chapter 5 of Programming Perl; Recipe 13.1; Recipe 13.9; Recipe 13.13