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'
        ];

我为什么在乎?因为当我尝试use使用 CGI::Application::Plugin::* 类时,它希望我CGI::Application已经在编译时继承自。插件类尝试add_callback在我的类上作为类方法调用,但不能,因为我@ISA的尚未设置。

解决这个问题的最佳方法是什么?@ISA在一个块中手动调整会BEGIN干扰MooseX::NonMoose吗?

编辑

以下似乎有效,但我觉得它令人反感:

package MyApp::CGI;

use Moose;
use MooseX::NonMoose;

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

我对 Moose 的内部结构知之甚少(或任何东西,真的),不知道这是否是个好主意。

4

1 回答 1

5

我觉得use base 'CGI::Application'; extends 'CGI::Application';这并不可怕,因为它正是你需要的:

  • 在编译时,@ISAcontains'CGI::Application'完全满足 CGI::Application::Plugin::* 的使用要求
  • 在运行时,您的类是CGI::Application的Moose后代,具有所有随之而来的好处(能够使用 Moosey 元优点设计您的类的组合)。只有在遇到该行之后,才会完成依赖于语句完成的工作的任何工作(即在您的类上调用方法):您的类源自该语句并且您安装了一个元类。extends 'CGI::Application'extendsMoose::Object

也就是说,jrockway 的解决方案也应该有效:

BEGIN { extends 'CGI::Application' }

...从您需要的时候开始,您会比计划提前一点点获得所有 Moosey 元优点,而且它不应该提前,前提是您已经调用use Moose并且use MooseX::NonMoose为了定义extends.

(附录:现在我正在考虑创建在编译时强制解析关键字的能力的编译复杂性,例如它们是否被包装在一个BEGIN块中。例如,如果 Moose.pm 声明use compiletime qw(extends)。它肯定会是一块不错的语法糖。)

于 2009-11-01T05:09:39.517 回答