[ Team LiB ] |
Recipe 13.6 Cloning Constructors13.6.1 ProblemYou want to write a constructor method that might be invoked on an existing object, and if so, to use that object for default values. 13.6.2 SolutionStart 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 DiscussionSometimes 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. 13.6.4 See Alsoperlobj(1) and Chapter 12 of Programming Perl; Recipe 13.1; Recipe 13.10; Recipe 13.13 |
[ Team LiB ] |