| Category: | Miscellaneous |
| Author/Contact Info | |
| Description: | This grew out of Interfaces in Perl?. This module provides a
mechanism for creating what are called abstract base
classes - classes that do not themselves define certain
methods but impose an automatic check that they have been
properly defined in derived classes. Here is an example where Foo and Bar are two abstract base classes and Baz inherits from them. This was (not surprisingly) my test example. First Foo.pm, which requires a method called foo: Now Bar which is another abstract class inheriting from Foo, implementing foo, and requiring bar. I have shown the other way to declare an abstract method: And finally, Baz.pm, a derived class inheriting from Bar:
UPDATE Oh, and I added a version number. :-)
UPDATE 2
UPDATE 3 |
package AbstractClass;
$VERSION = 0.12;
use Carp;
sub bless ($@) {
my $class = $_[1] || caller();
if (exists $Registered{$class}) {
confess("Cannot bless objects into abstract class $class");
}
else {
CORE::bless(shift, $class);
}
}
$text = '
#line 1 "(AbstractClass loaded for MYPACK)"
package MYPACK;
sub import {
my $pkg = shift;
return if $pkg eq "MYPACK";
foreach my $meth (@ABSTRACT_METHODS) {
my $does = $pkg->can($meth);
if (not defined($does)) {
Carp::croak("Class $pkg must define $meth for class MYPACK");
}
else {
my $override = MYPACK->can($meth);
if (defined ($override) and $does == $override) {
Carp::confess("Class $pkg cannot inherit $meth from MYPACK")
+;
}
}
}
$pkg->SUPER::import(@_);
}
1;
';
sub import {
shift; # Don't need my class name
my $base = caller();
$Registered{$base}++;
*{"$base\::bless"} = *bless;
@{"$base\::ABSTRACT_METHODS"} = @_;
my $eval_str = $text;
$eval_str =~ s/MYPACK/$base/g;
eval($eval_str) or confess("Cannot execute:\n$eval_str\n\nError $@")
+;
}
1;
__END__
=head1 NAME
AbstractClass - Makes classes into abstract classes.
=head1 SYNOPSIS
In module SomeAbstractClass.pm:
package SomeAbstractClass;
use AbstractClass;
@ABSTRACT_METHODS = qw(foo bar);
or more compactly:
package SomeAbstractClass;
use AbstractClass qw(foo bar);
=head1 DESCRIPTION
An abstract class is a class which defines methods
that must be overridden in classes that wish to inherit
from it which are not themselves abstract classes.
Normally the abstract class will then provide methods
whose implementations need these methods to exist.
Whether or not it is an abstract class, it would crash
at some point if the methods were missing. By moving
the check to when you first load the class, you can find
problems immediately and get better reporting of the
requirement.
It is customary to not have any objects in an abstract
class. This module provides some enforcement of this
rule by overriding bless in abstract classes.
=head1 BUGS
Abstract classes are implemented with special import
functions. Therefore this does not play well with
Exporter. Also due to unfortunate restrictions in the
implementation of Perl's SUPER pseudo-package, multiple
inheritance will not play well with abstract classes. If
you wish to use the capabilities of abstract classes and
multiple inheritance, you may wish to look at the more
intrusive Class::Contract.
This mechanism also means that if you define multiple
classes in a single file then you must manually import
each derived class to test it. When each class is in its
own module, this happens automatically when you use the
module.
It is not hard to get around the rule that objects cannot
belong to an abstract class. To fix that would require
overriding the core bless method, which brings up issues
of its own.
=head1 AUTHOR
AbstractBase was written by Ben Tilly <ben_tilly@hotmail.com>.
This module may be copied and modified on the same terms as
Perl itself.
|
|
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: AbstractClass
by merlyn (Sage) on Dec 02, 2000 at 07:51 UTC | |
by tye (Sage) on Dec 02, 2000 at 10:02 UTC | |
by Anonymous Monk on Dec 07, 2000 at 01:48 UTC | |
|
Re: AbstractBase
by Dominus (Parson) on Dec 01, 2000 at 18:59 UTC | |
by tilly (Archbishop) on Dec 01, 2000 at 19:26 UTC |