MooseX::NonMoose类中混入(mixins)的问题

5
请看以下内容:
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;

... 

编译时的输出结果如下:
begin isa = $VAR1 = [
          'Moose::Object'
        ];
runtime isa = $VAR1 = [
          'CGI::Application',
          'Moose::Object'
        ];

为什么我关心这个问题呢?因为当我尝试使用CGI::Application::Plugin::*类时,它期望我在编译时已经从CGI::Application继承。插件类试图在我的类上调用add_callback作为类方法,但无法实现,因为我的@ISA还没有设置。
解决这个问题的最佳方法是什么?在BEGIN块中手动调整@ISA是否会干扰MooseX::NonMoose?
编辑
以下似乎可行,但我觉得很冒犯:
package MyApp::CGI;

use Moose;
use MooseX::NonMoose;

use base 'CGI::Application';
extends 'CGI::Application';

我对Moose内部了解不足(实际上是一无所知),不知道这是否是一个好主意。


1
值得注意的是,“use”作为“BEGIN”的同义词是一种常见的反模式。另请参阅:“use ok ...”。 - jrockway
jrockway:那应该是一个答案,而不是评论。 - ysth
1个回答

5
我认为use base 'CGI::Application'; extends 'CGI::Application';并不可怕,因为它恰好满足你的需求:
  • 在编译时,@ISA包含'CGI::Application',完全满足CGI::Application::Plugin::*的使用要求。
  • 在运行时,您的类是Moose的后代,继承自CGI::Application,具有所有随之而来的好处(能够使用Moosey meta goodness设计类的组合)。只有在遇到extends 'CGI::Application'语句后才会执行任何工作(即调用类上的方法),这些方法依赖于extends语句所做的工作:使您的类继承自Moose::Object并安装元类。

话虽如此,jrockway的解决方案也应该可以工作:

BEGIN { extends 'CGI::Application' }

...这里你可以提前获取所有Moosey元数据好处,只要你已经调用了use Mooseuse MooseX::NonMoose来定义extends,它就不应该太提前。

(补充说明:现在我正在考虑创建强制编译时解析关键字的复杂性,就像它们被包装在BEGIN块中一样立即解析。例如,如果Moose.pm声明use compiletime qw(extends),那么它肯定是一个不错的语法糖。)


1
使用 BEGIN 块是有效的。 我会把++给jrockaway,但他没有在答案中发布它。 :) - friedo
1
Ether: Devel::BeginLift 可以实现这个功能。 - jrockway

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接