This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

Class Collections: Provide the ability to overload classes

=head1 VERSION

   Maintainer: Greg Williams <[EMAIL PROTECTED]>
   Date: 17 Sep 2000
   Mailing List: [EMAIL PROTECTED]
   Number: 254
   Version: 1
   Status: Developing

=head1 ABSTRACT

Currently, class methods can be overloaded through sub-classing. This
functionality is perhaps the most compelling aspect object oriented
programming offers.  This mechanism allows one to extend the functionality of
pre-existing code without significant copying or rewriting.  However, there
exists situations in which it is desirable not to extend methods, but entire
classes.

It is proposed that classes be able to be grouped into collections.
Collections would have the ability to inherit from other collections just as
classes inherit from other classes.  A sub-collection would overload
super-collection classes exactly like subclasses overload superclass methods.

=head1 DESCRIPTION

In a typical HASA relationship, the method call to construct the encapsulated
object must make the call against either a class name, or a scalar containing
the class name.  In either case the name of the class must be known and hard
coded in some part of the code.

Consider two classes, Forest and Frog (both of which you found on CPAN).  A
Forest object HASA Frog object.  The Frog object has a method C<speak> which
prints the noise a frog makes. The Forest object has a method C<make_noise>
which prints a noise you might hear in the forest (like a frog!):

     package Forest;
     sub new {
       my $class = shift;
       my $frog = Frog->new;
       return bless( { frog => $frog }, $class );
     }

     sub make_noise {
       my $self = shift;
       $self->{frog}->speak; # prints "ribbit ribbit";
     }

     package Frog;
     sub new {
       my $class = shift;
       return bless( {}, $class );
     }

     sub speak () { print "ribbit ribbit"; }
     sub jump ();
     sub croak (); # ;-)

In English this is fine, but now let's say you need the Forest class to work in
Japanese as well (Japanese frogs 'kerokero', they don't 'ribbit').  The Frog
class is maintained by another developer however, and you'd rather not make
changes to it directly.  You can subclass Frog and provide your own C<speak>
method like so:

     package Frog::Japanese;
     @ISA = qw( Frog );
     sub speak { print "kerokero"; }

Here's where the problem lies.  Even though we now have a subclass of Frog, the
Forest class is still referencing the original Frog class and not
Frog::Japanese.  In order for Forest to reference Frog::Japanese, you 
could edit
the Forest class and change all occurances of Frog to Frog::Japanese, but that
is probably not wise.  Firstly, although you may be using a relativly small
subset of the features of Forest, the code may contain many references to the
Frog class, each of which you must now change.  Secondly, and most importantly,
by maintaining a locally modified version of Forest you make it difficult to
upgrade Forest from CPAN in the future (this rationale just stopped you from
making changes to the Frog class, after all).

Assuming you did change your copy of Forest, you'd end up with a C<new>
constructor similar to this:

     package Forest;
     sub new {
       my $class = shift;
       my $frog = Frog::Japanese->new;
       return bless( { frog => $frog }, $class );
     }

Now the Forest is specifically Japanese though, and can't be used in English
anymore!  In perl 5, a logical solution is to subclass Forest for a specific
locale, with each subclass specifying which language (class) to use:

     package Forest::Japanese;
     @ISA = qw( Forest );
     sub frog_class { 'Frog::Japanese' };

     package Forest::English;
     @ISA = qw( Forest );
     sub frog_class { 'Frog' };

     package Forest;
     sub new {
       my $class = shift;
       my $frog = $class->frog_class->new;
       return bless( { frog => $frog }, $class );
     }

At this point, we must stop and question whether all this work should be
necessary just to change one return value of one method.  A better solution
(albeit not currently possible) would be to 'overload' the Frog class 
with a new
Japanese version (also named 'Frog').  The Japanese version of the Frog class
would inherit (in a slightly altered sense) everything but the C<speak> method
from the CPAN version of Frog, and all static calls to Frog methods would
actually be made against the new Japanese version.

Another example of where this feature would be helpful is when a large
number of classes inherit from a single superclass and it is 
desirable to extend
said superclass without making modifications to any subclasses.  This has
tremendously powerful implications in the area of data inheritance as 
this would
allow the addition of fields to a superclass through L<fields> (or the feature
of similar functionality in perl6) thus affecting all subclasses of that
superclass.

Therefore, it is proposed that a method of defining collections of classes be
implemented.  A collection would encompass a set of classes that inherited from
and referenced one another (most likely a full application or library).  By
creating a new collection with only the classes you wish to change (such as a
superclass) and having this new collection inherit from the base collection,
classes will become able to overload other classes.

I am unsure of what syntax this feature would employ, both in declaring
membership of a collection, and in declaring inheritance from a collection.  I
can envision a pragma that might suffice:

     package Frog;
     use collection member => 'Japanese'; #declares collection membership
     use collection isa => 'BaseImplentation'; #declares collection inheritance

but am interested to hear suggestions for other ways this might be 
accomplished.

I am unaware of any OO language that allows overloadable classes as described
here, and have seen them described only once, but have run into many situations
in which they would make sense.  I would like to discuss the 
possibility of this
feature for perl 6, and hear what others perceive as the implications of this
sort of feature on the perl object model (both good and bad).

=head1 IMPLEMENTATION

I'm not big on internals, but:

=over 4

=item * Class Names Would No Longer Be Unique

A given class name would not be guaranteed to be unique.  A 
namespace/collection
pair would specify a unique package (for lack of a better term).

=item * Method Lookup

Method lookups would need to examine the collection inheritance tree to
determine which class (that is, in which collection) to dispatch method
calls to.

=back

=head1 REFERENCES

Tim Sweeney, "A Critical Look at Programming Languages"
http://www.gamespy.com/legacy/articles/devweek_b.shtm


Reply via email to