Skip to content

Instantly share code, notes, and snippets.

@draegtun
Created September 8, 2011 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save draegtun/1204277 to your computer and use it in GitHub Desktop.
Save draegtun/1204277 to your computer and use it in GitHub Desktop.
One Base Class to Rule Them All (in Perl)
package MooseBase;
use Moose;
use Class::MOP;
# One Base Class to Rule Them All!
#
# see: https://www.destroyallsoftware.com/blog/2011/one-base-class-to-rule-them-all
# https://github.com/garybernhardt/base/blob/master/lib/base.rb
# http://news.ycombinator.com/item?id=2963525
has anon_class => (
is => 'ro',
isa => 'Class::MOP::Class',
default => sub { Class::MOP::Class->create_anon_class }
);
sub BUILD {
my @classes = do {
# get all defined (Moose) classes
my @universe = grep { $_ ne __PACKAGE__ } Moose::Object->meta->subclasses;
# get MooseBase subclasses because we don't want to look in these!
my @subclasses = __PACKAGE__->meta->direct_subclasses;
# Universe minus MooseBase derived classes
grep { my $class = $_; grep { $_ ne $class } @subclasses } @universe;
};
# make this objects anon_class parents all the other Moose classes!
shift->anon_class->superclasses( @classes );
}
sub AUTOLOAD {
my $self = shift;
my ($method_name) = our $AUTOLOAD =~ m/.*::(.*)/;
if ($self->anon_class->find_method_by_name( $method_name )) {
# only going to use first method it finds in object dispatch
my $instance = $self->anon_class->new_object;
$instance->$method_name( @_ );
return $instance; # or $self ??
}
else { die "No method found in meta!" }
}
no Moose;
1;
#!/usr/bin/env perl
use 5.014;
use warnings;
{
package Foo;
use Moose;
sub bar { say "bar" }
}
{
package Baz;
use Moose;
extends 'Foo';
has greeting => (is => 'ro', isa => 'Str', default => 'Hello' );
sub baz {
my ($self, $text) = @_;
say $self->greeting, ' ', uc $text;
}
}
{
package Cantaloupe;
use Moose;
extends "MooseBase";
}
my $x = Cantaloupe->new;
say join ":", $x->anon_class->get_all_method_names;
$x->baz("there"); # from Baz
$x->bar; # from Foo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment