NAME
OOP::Perlish::Class::Abstract
DESCRIPTION
Quickly and easily create abstract classes, which can easily be tested for via 'isa' or OOP::Perlish::Class::Accessor->implements( [ 'ClassA', 'ClassB' ] ); ('implements' is a polymorphism test, not an inheritance test, and is generally preferred)
SYNOPSIS
- Defining an abstract class
-
package MyAbstractClass; use base qw(OOP::Perlish::Class::Abstract); BEGIN { __PACKAGE__->_interfaces( my_interface => 'required', my_optional_interface => 'optional', my_optional_but_true => 'optional_true', ); };
- Later in an implementation class:
-
package MyImplementationClass; use base qw(MyAbstractClass); sub my_interface { my ($self) = @_; return 'foo'; }
- Meanwhile, in a consuming class
-
package MyConsumerClass; use base qw(OOP::Perlish::Class); BEGIN { __PACKAGE__->_accessors( foo => { type => 'OBJECT', implements => [ 'MyAbstractClass' ], }, ); }; sub quux { my ($self) = @_; return $self->foo()->my_interface(); }
- And finally, when used:
-
my $foo = MyImplementationClass->new(); my $bar = MyConsumerClass->new( foo => $foo ); print $bar->quux() . $/;
USAGE
The module provides handlers for 'required', 'optional', and 'optional_true' types of interface definitions via the following built-in method factories:
############################################################################################
## Return a subroutine for the required interfaces
############################################################################################
sub ____oop_perlish_class_interface_impl_required
{
my ( $self, $name ) = @_;
my $class = ref($self) || $self;
$self->____OOP_PERLISH_CLASS_REQUIRED_INTERFACES()->{$name} = 1;
return sub { confess("Interface $name is required, but was not defined in $class (nor in the ancestory of $class)"); };
}
############################################################################################
## Return a subroutine for the optional (false) interfaces
############################################################################################
sub ____oop_perlish_class_interface_impl_optional
{
my ( $self, $name ) = @_;
return sub { return; };
}
############################################################################################
## Return a subroutine for optional_true interfaces
############################################################################################
sub ____oop_perlish_class_interface_impl_optional_true
{
my ( $self, $name ) = @_;
return sub { return 1; };
}
if you wish to add additional handlers for an abstract class; simply define a method with the type prefixed with ____oop_perlish_class_interface_impl_
e.g.:
sub ____oop_perlish_class_interface_impl_my_type
{
return sub { return 'default sub for my_type'; };
}
Which would allow you to specify in the _interfaces() call
BEGIN {
__PACKAGE__->_interfaces(
my_interface => 'my_type',
);
};
This is mostly useful for specifying default interfaces that are expected to return references to (possibly empty) hashes or arrays.
DIAGNOSTICS
invokes confess() whenever a method is called that was 'required' but never defined.
invokes confess() whenever a type is specified in __PACKAGE__->_interfaces() that does not have a handler defined.
invokes confess() whenever an object is instantiated via new and is missing a required interface definition;