Problem with mixins in a MooseX::NonMoose class
Consider the following:
package MyApp::CGI;
use Moose;
use MooseX::NonMoose;
use Data::Dumper;
extends 'CGI::Application';
BEGIN {
print "begin isa = " . Dumper \@MyApp::CGI::ISA;
};
print "runtime isa = " . Dumper \@MyApp::CGI::ISA;
...
The output when this compiles is:
begin 开发者_JAVA百科isa = $VAR1 = [
'Moose::Object'
];
runtime isa = $VAR1 = [
'CGI::Application',
'Moose::Object'
];
Why do I care? Because when I try to use
a CGI::Application::Plugin::* class, it expects me to be inheriting from CGI::Application
at compile-time already. The plugin class tries to call add_callback
as a class method on my class, but can't, because my @ISA
isn't set up yet.
What's the best way to solve this? Would tweaking @ISA
manually in a BEGIN
block interfere with MooseX::NonMoose
?
Edit
The following appears to work, but I find it offensive:
package MyApp::CGI;
use Moose;
use MooseX::NonMoose;
use base 'CGI::Application';
extends 'CGI::Application';
I don't know enough (or anything, really) about Moose internals to know if this is a good idea.
I don't find use base 'CGI::Application'; extends 'CGI::Application';
to be terribly ghastly because it does precisely what you need:
- At compile-time,
@ISA
contains'CGI::Application'
, which exactly satisfies the usage requirements of CGI::Application::Plugin::* - At runtime, your class is a Moose descendant of CGI::Application, with all the ensuing benefits (being able to design the composition of your class with Moosey meta goodness). It's only after the
extends 'CGI::Application'
line is encountered that any work is done (i.e methods are called on your class) that rely on the work done by theextends
statement: that your class descends fromMoose::Object
and you have a meta-class installed.
That said, jrockway's solution should also work:
BEGIN { extends 'CGI::Application' }
...where you get all the Moosey meta goodness just a little ahead of schedule from when you need it, and it shouldn't be too ahead of schedule, provided you already called use Moose
and use MooseX::NonMoose
in order to define extends
.
(Addendum: Now I'm pondering the complilational complexities of creating the ability to force the parsing of a keyword at compile-time that are parsed immediately such as if they were wrapped in a BEGIN
block. e.g. something like if Moose.pm declared use compiletime qw(extends)
. It would be a nice piece of syntactic sugar for sure.)
精彩评论