NAME

Method::Delegation - Easily delegate methods to another object

VERSION

Version 0.03

SYNOPSIS

package Order;

use Method::Delegation;
delegate(
    methods => [qw/name customer_number/],
    to      => 'customer',
);

EXPORT

delegate

Calling delegate(%args) installs one or more methods into the current package's namespace. These methods will delegate to the object returned by to.

Arguments to delegate are as follows (examples will be after):

EXAMPLES

Basic Usage

Delegating a single method:

delegate(
    methods => 'name',
    to      => 'customer',
);
# equivalent to:
sub name {
    my $self = shift;
    return $self->customer->name;
}

Delegating several methods:

delegate(
    methods => [/name rank serial_number/],
    to      => 'soldier',
);
# equivalent to:
sub name {
    my $self = shift;
    return $self->soldier->name;
}
sub rank {
    my $self = shift;
    return $self->soldier->rank;
}
sub serial_number {
    my $self = shift;
    return $self->soldier->serial_number;
}

Delegating, but renaming a method:

delegate(
    methods => {
        customer_name   => 'name',
        customer_number => 'number,
    },
    to => 'customer',
);
# equivalent to:
sub customer_name {
    my $self = shift;
    return $self->customer->name;
}
sub customer_number {
    my $self = shift;
    return $self->customer->number;
}

Advanced Usage

Delegating to an object that might not exist is sometimes necessary. For example, in DBIx::Class, you might have an atttribute pointing to a relationship with no corresponding entry in another table. Use if_true for that:

delegate(
    methods => 'current_ship',
    to      => 'character_ship',
    if_true => 'character_ship',
);
# equivalent to:
sub current_ship {
    my $self = shift;
    if ( $self->character_ship ) {
        return $self->character_ship;
    }
    return;
}

As an optimization for the common case, you can use maybe_to if the object you're delegating to might not exist.

delegate(
    methods  => 'current_ship',
    maybe_to => 'character_ship',
);

Note: the if_true attribute doesn't need to point to the same method, but usually it does. If it points to another method, it simply checks the truth value of the response to determine if the original delegate will be called.

Sometimes, if the object you're delegating to another object, you want a different value than undef being returned if the object isn't there. Use the else_return attribute. The following will return 0 (zero) instead of undef if current_weapon isn't found:

delegate(
    methods => {
        weapon_damage   => 'damage',
        weapon_accurace => 'accuracy',
    },
    to          => 'current_weapon',
    if_true     => 'current_weapon',
    else_return => 0,
);

AUTHOR

Curtis "Ovid" Poe, <curtis.poe at gmail.com>

BUGS

Please report any bugs or feature fequests via the Web interface at https://github.com/Ovid/method-delegation/issues. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc Method::Delegation

You can also look for information at:

SEE ALSO

Method::Delegation was developed for the narrative sci-fi game Tau Station. We like it because the syntax is simple, clear, and intuitive (to us). However, there are a few alternatives on the CPAN that you might find useful:

ACKNOWLEDGEMENTS

This code was written to help reduce the complexity of the narrative sci-fi adventure, Tau Station. As of this writing, it's around 1/3 of a million lines of code (counting front-end, back-end, tests, etc.), and anything to reduce that complexity is a huge win.

Thanks to ilmari for the if_true => 1 shortcut suggestion.

LICENSE AND COPYRIGHT

This software is Copyright (c) 2019 by Curtis "Ovid" Poe.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)