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:
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