-
Notifications
You must be signed in to change notification settings - Fork 19
Constructors
Please see the main page of the repo for the actual RFC. As it states there:
Anything in the Wiki should be considered "rough drafts."
Click here to provide feedback.
To better understand this document, you should read Class Phases.
Thanks to Damian Conway for pointing out some problems with the first constructor approach.
Note that Moo/se BUILDARGS and BUILD have been renamed to CONSTRUCT and
ADJUST, respectively, because their semantics don't entirely match either
Moo/se or Raku.
This is a first pass at declaring how constructors work, taking into consideration known limitations with the attributes. Specifically:
- You cannot declare constructor arguments unless they have a corresponding slot.
- We don't have first-class constructors in Perl.
Slots are defined via has $varname;. This does nothing outside of declaring the slot. Nothing at all. Instead, if we wish to specify arguments for the constructor, we use the :new syntax: has $varname :new;.
Not passing any of these to the constructor means the value may not be passed to the constructor, but the CONSTRUCT phase can compensate for that.
Nothing is set in stone.
- All Corinna constructors take a an even-sized list of named arguments.
- A single argument hashref, as allowed in Moose, is not allowed unless a
CONSTRUCTphase intercepts it and rewrites it to an even-sized list. - The constructor is named
new. - Slots (instance variables) are assigned values from constructor arguments according to their corresponding
:newattributes. This is done internally via theNEWmethod. - Unknown attributes passed to the constructor are fatal unless a
CONSTRUCTphase is supplied to handle (and remove) those arguments -
Before the constructor is called, we invoke an implicit
CONSTRUCTphase from theUNIVERSAL::Corinnaclass. TheCONSTRUCTblock is required to return an even-sized list of key/value pairs. -
After the constructor is called, we invoke an implicit
ADJUSTphase from theUNIVERSAL::Corinnaclass - Constructor arguments are named after the slot identifier, unless a
:name($new_name)attribute is supplied.
Let's consider this Box class.
class Box {
has ($width, $height, $depth) :new :reader :isa(Num);
has $volume :reader :builder;
method _build_volume() { $width * $height * $depth }
}
my $box = Box->new(height => 7, width => 7, depth => 7);
say $box->volume; # 343But maybe we want to call Box->new(7) to get a cube. We do this by
overriding the CONSTRUCT phase.
CONSTRUCT (@args) {
if ( @args == 1 ) {
my $num = $args[0];
@args = map { $_ => $num } qw<height width depth>;
}
return @args;
}
If you don't like messing around with CONSTRUCT, just create an alternate
constructor:
shared method new_cube ($class, $length) {
$class->new(length => $length);
}
Corinna—Bringing Modern OO to Perl