The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Class::Constructor - Simplify the creation of object constructors

SYNOPSIS

    package MyPackage;

    # Note if you don't have the CLASS package installed,
    # you can use the __PACKAGE__ keyword instead

    use CLASS;
    use base qw/ Class::Constructor Class::Accessor /;

    my @Accessors = qw(
        some_attribute
        another_attribute
        yet_another_attribute
    );

    CLASS->mk_accessors(@Accessors);
    CLASS->mk_constructor(
        Name           => 'new',
        Auto_Init      => \@Accessors,
    );

DESCRIPTION

Simplifies the creation of object constructors.

Instead of writing:

    sub new {
        my $proto = shift;
        my $class = ref $proto || $proto;
        my $self = {};
        bless $self, $class;

        my %args = @_;
        foreach my $attr ('first_attribute', 'second_attribute') {
            $self->$attr($args{$attr});
        }

        $self->_init();

        return $self;
    }

You can just write:

    CLASS->mk_constructor(
        Auto_Init      => [ 'first_attribute', 'second_attribute' ],
    );

There are other features as well:

Automatically call other initialization methods.

Using the Init_Methods method of mk_constructor, you can have your constructor method automatically call one or more initialization methods.

Automatic Construction of objects of Subclasses

Your constructor can bless objects into one of its subclasses.

For instance, the Fruit class could bless objects into the Fruit::Apple or Fruit::Orange classes depending on a parameter passed to the constructor.

See Subclass_Param for details.

METHOD

mk_constructor

    CLASS->mk_constructor(
        Name           => 'new',
        Init_Methods   => [ '_init' ],
        Subclass_Param => 'Package_Type',
        Auto_Init      => [ 'first_attribute', 'second_attribute' ],
    );

The mk_constructor method creates a constructor named Name in CLASS's namespace.

Name

The name of the constructor method. The default is new.

Init_Methods

Cause the created constructor to call the listed methods on all new objects that are created via the constructor.

    Foo->mk_constructor(
        Name           => 'new',
        Init_Methods   => '_init',
    );

    my $object = Foo->new; # This calls $object->_init();


    Foo->mk_constructor(
        Name           => 'new',
        Init_Methods   => [ '_init', '_startup' ],
    );

    my $object = Foo->new; # after construction, new()
                           # calls $object->_init(),
                           # then $object->_startup()
Auto_Init

A list of attributes that should be automatically initialized via the parameters to the constructor.

For each name/value pair passed to the constructor, the constructor will call the method named name with the parameter of value.

For instance, if you make your constructor with:

    Fruit->mk_constructor(
        Auto_Init      => [ 'size', 'colour' ],
    );

And you call the constructor with:

    use Fruit;
    my $fruit = Fruit->new(
        size   => 'big',
        colour => 'red',
    );

Then, internally, the new constructor will automatically call the following methods:

    $fruit->size('big');
    $fruit->colour('red');

Note that by default, Class::Constructor converts names to lower case. See CASE SENSITIVITY, below.

Disable_Case_Mangling

Set this to a true value if you don't want Class::Constructor to force attribute names to lower case. See CASE SENSITIVITY, below.

Method_Name_Normalizer

Another name for Disable_Case_Mangling, above.

Method_Name_Normalizer

Custom subroutine for converting a parameter passed to auto_init into a attribute name. See CASE SENSITIVITY, below.

Class_Name_Normalizer

Custom subroutine for converting a subtype class into a Perl class name. See CASE SENSITIVITY, below.

Subclass_Param

You can cause the constructor to make instances of a subclass, based on the a special parameter passed to the constructor:

    # Fruit.pm:
    package Fruit;
    Fruit->mk_constructor(
        Name           => 'new',
        Subclass_Param => 'Type',
    );

    sub has_core { 0 };

    # Fruit/Apple.pm:
    package Fruit::Apple;
    use base 'Fruit';

    sub has_core { 1 };

    # main program:
    package main;

    my $apple = Fruit->new(
        Type => 'Apple',
    );

    if ($apple->has_core) {
        print "apples have cores!\n";
    }
Dont_Load_Subclasses_Param

The name of the parameter that will be checked by the constructor to determine whether or not subclasses specified by Subclass_Param will be loaded or not. This is mainly useful if you are writing test scripts and you want to load in your packages manually.

For instance:

    # Fruit.pm:
    package Fruit;
    Fruit->mk_constructor(
        Name                     => 'new',
        Subclass_Param           => 'type',
        Dont_Load_Subclass_Param => 'Dont_Load_Subclass',
    );

    # main program:
    package main;

    my $apple = Fruit->new(
        Type               => 'Apple',
        Dont_Load_Subclass => 1,
    );

Now when the $apple object is created, the constructor makes no attempt to require the Fruit::Apple module.

CASE SENSITIVITY

By default, attribute names are forced to lower case and the case of Auto_Init parameter names passed to the constructor doesn't matter.

So the following call to a constructor:

    my $fruit = Fruit->new(
        SiZE   => 'big',
        colOUR => 'red',
    );

Is actually equivalent to:

    my $fruit = Fruit->new();
    $fruit->size('big');
    $fruit->colour('red');

You can disable this behaviour by setting Disable_Case_Mangling to a true value:

    package Fruit;
    Fruit->mk_constructor(
        Disable_Case_Mangling => 1,
    );

Now the parameters are left unchanged:

    my $fruit = Fruit->new(
        SiZE   => 'big',
        colOUR => 'red',
    );

    # equivalent to:
    my $fruit = Fruit->new();
    $fruit->SiZE('big');
    $fruit->colOUR('red');

Similarly for class names as passed via Subclass_Param, they are converted to lower case and then the first letter is uppercased.

    # the following creates a Fruit::Apple
    my $apple = Fruit->new(
        Type => 'APPLE',
    );

This behaviour is also disabled via Disable_Case_Mangling:

    package Fruit;
    Fruit->mk_constructor(
        Subclass_Param        => 'Type',
        Disable_Case_Mangling => 1,
    );

    # the following creates a Fruit::APPLE
    my $apple = Fruit->new(
        Type => 'APPLE',
    );

If you want to customize the way Class::Constructor changes method names, you can pass subroutines to do the work:

    package Fruit;
    Fruit->mk_constructor(
        Subclass_Param         => 'Type',
        Method_Name_Normalizer => sub { '_' . $_[0] }, # precede methods with underscore
        Class_Name_Normalizer  => sub { uc $_[0] },    # class names to uppercase
    );

    # the following creates a Fruit::APPLE
    my $apple = Fruit->new(
        Type   => 'apple',
        SiZE   => 'big',
        colOUR => 'red',
    );

    # and this is equivalent to:
    my $apple = Fruit->new(
        Type   => 'apple',
    );

    $apple->_SiZE('big');
    $apple->_colOUR('red');

AUTHOR

Michael Graham <mag-perl@occamstoothbrush.com>

Copyright (C) 2001 Michael Graham. All rights reserved. This program is free software. You can use, modify, and distribute it under the same terms as Perl itself.

The latest version of this module can be found on http://www.occamstoothbrush.com/perl/

SEE ALSO

Class::Accessor
CLASS