sub ego
{
$_[0] ||= {};
my $corona= shift @_;
my $pkg= caller();
for my $ego ( $corona->{$pkg} ) {
$_= shift @_
if @_;
$_ ||= {};
return $_;
}
}
Yes, a much simpler and more direct solution to some of the problems that "inside-out" objects are being promoted to address1.
Note that this suffers from the usual short-comings of caller. The calling "package" is quite an ambiguous thing and calller returns only one meaning of that. I have personally written methods that have many different values for the different interpretations of "calling package" and I bet your module would fail in such situations (just like SUPER:: and its replacements fail).
Consider:
package Devel::HandyMethods;
sub Handy::GetOrSet
{
my $self= ego( shift @_ );
# ...
}
package My::Module::_private;
*My::Module::foo= \&Handy::GetOrSet;
sub My::Module::bar
{
my $self= ego( shift @_ );
# ...
}
It is unfortunate that caller provides no way to get "My::Module" when Handy::GetOrSet() gets called via "SubclassOf::My::Module"->foo() (assuming @SubclassOf::My::Module::ISA= 'My::Module'). So you should provide ways for module authors to override how you determine which package name to use.
And thanks for pointing out some of the stupidity of "inside-out" objects. I still boggle a bit that such a convoluted technique for inheriting from objects that were not designed to be inherited from has become the most touted method for doing all Perl OO. Saner alternatives need more touting. (:
1 Note that "inside-out" objects were first created to address being able to subclass arbitrary objects but "inside-out" objects are now being heavily touted as the way to implement all objects and your idea certainly has a lot of advantages as far as a "best practice" way of implementing objects. But your method doesn't deal with the original "subclass arbitrary object" problem.
Also, you don't address the "compile-time checking of member variable names" issue that "inside-out" objects address. Some would "use fields" as another solution. I prefer to have an array for an object and use constant subroutines for member variable names.
|