$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. | [reply] |
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. | [reply] [d/l] |
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... | [reply] [d/l] [select] |
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. | [reply] [d/l] |
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. | [reply] [d/l] |
| [reply] |
| [reply] |
Don't call your contructors explicitly throughout the code.
Use Class Factory instead. | [reply] |