http://qs1969.pair.com?node_id=617945

The inside-out techique of class construction has shown that inheritance in object oriented Perl can work as smoothly as it does in dedicated OO languages. Unlike traditional Perl classes, one or more inside-out classes can be made base classes of any other Perl class, inside-out or not. The other way around, any class can become a base class of an inside-out class, though only one of the base classes can be non-inside-out.

The price for this freedom is also well known. Inside-out classes are not automatically garbage-collected and thread-cloned. Each class must take care of that itself -- there is no general way of doing that because only the class knows which data it defines. A related problem, less often discussed but also serious, is serialization. Whether for viewing or for object persistence, the usual tools (Data::Dumper, Storable) know nothing about the object's data in inside-out storage. A class can easily provide the necessary hooks (STORABLE_freeze and STORABLE_thaw, for instance), but each class must do so individually.

There are two essentials in the working of inside-out classes that are key to the freedom of inheritance:

  • - Each class can freely define the data it wants to associate with an object, independent of what other classes think the object contains.
  • - No method of an inside-out class accesses (de-referrences) the body of its objects directly.
  • These essentials can be realized in a different way. If every object had, for every potential class, an individual reference to present to that class instead of its body, both conditions would be met. Each class would have an individual set of data associated with each object. To access the data, it would de-reference the object's alter ego and not the body itself.

    To show that the concept works I have put together a module named Alter, which exports a function named ego(). ego() can be used on every reference (object) to store and retrieve an alternative reference which depends on the caller of ego(). Thus every class can establish its individual view of and object, independent of the views of other classes.

    Here is a trivial class that implements a single accessor method. It doesn't demonstrate the salient features of Alter::ego but shows how the implementation of a standard class would look like. Essentially it works like a standard (not inside-out) Perl class, except that all methods invoke the object's Alter::ego before accessing its data.

    #!/usr/local/bin/perl use strict; use warnings; $| = 1; my $x = MyClass->new( 'Otto'); print $x->name, "\n"; $x->name = 'Erich'; print $x->name, "\n"; exit; ######################################################## package MyClass; use blib; use Alter qw( ego); sub new { my $class = shift; bless( \ my $o, $class)->init( @_); } sub init { my $ob = shift; ego $ob, { name => shift }; # set up alter ego as a hash ref $ob; } sub name :lvalue { ego( shift)->{ name} } # access the alter ego __END__

    A preliminary implementation of Alter contains a (slightly) more extensive example. It is available here. The pod can be viewed there too. It's an XS module, so you need the right compiler to make it run. It is not extensively tested, but should be workable. Needless to say -- don't base any serious code on it, it's nothing but a proof of concept.

    Anno