如何使用与主脚本相同的文件中定义的Moose类?

Håk*_*and 4 perl moose

以下脚本p.pl工作正常:

use feature qw(say);
use strict;
use warnings;
use lib '.';
use P1;

my $obj = P1->new(name => 'John');
say "The name is: ", $obj->name;
Run Code Online (Sandbox Code Playgroud)

P1在文件中定义类的位置P1.pm:

package P1;
use Moose;

has name => (is => 'rw', isa => 'Str');

1;
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试将类移动P1.pm到主脚本中时:

#! /usr/bin/env perl

use feature qw(say);
use strict;
use warnings;

my $obj = P1->new(name => 'John');
say "The name is: ", $obj->name;

package P1;
use Moose;

has name => (is => 'rw', isa => 'Str');
Run Code Online (Sandbox Code Playgroud)

我收到错误:

Can't locate object method "name" via package "P1" at ./p.pl line 8.
Run Code Online (Sandbox Code Playgroud)

ike*_*ami 6

您正在尝试在执行调用之前使用该属性来has创建它.

内联模块的一种相对简单的方法如下:

use feature qw(say);
use strict;
use warnings;

use FindBin qw( $RealBin );
use lib $RealBin;

BEGIN {
   package P1;
   use Moose;

   has name => (is => 'rw', isa => 'Str');

   $INC{"P1.pm"} = 1;
}

use P1;

my $obj = P1->new(name => 'John');
say "The name is: ", $obj->name;
Run Code Online (Sandbox Code Playgroud)

请记住,它仍然不完全相同.例如,模块现在位于脚本中的三个pragma范围内.也许你应该使用App :: FatPacker或类似的.


hau*_*kex 5

has它只是一个在运行时执行的常规函数​​调用,所以直到你的运行后它才会运行say.

通常你是use一个Moose类,并且use Class;只是简称BEGIN { require Class; ... },因此通常,所有Moose函数has都将在执行useing 的脚本的编译期间执行.另请参阅perlmod中的"BEGIN,UNITCHECK,CHECK,INIT和END".

虽然我认为这不是最好的解决方案,但您可以将package P1;声明粘贴在一个BEGIN { ... }块中.或者,您可以package P1在主代码之前放置(在它自己的块中最好,因此它有自己的范围).

但是,首先要将类放在同一个文件中也有一些说法,例如参见In Perl中的答案,如何将多个类放在单个.pm文件中.