我需要定义一些模块并在同一个文件中使用它们。不,我不能改变要求。
我想做以下事情:
{
package FooObj;
sub new { ... }
sub add_data { ... }
}
{
package BarObj;
use FooObj;
sub new {
...
# BarObj "has a" FooObj
my $self = ( myFoo => FooObj->new() );
...
}
sub some_method { ... }
}
my $bar = BarObj->new();
但是,这会产生以下消息:
无法在@INC中找到FooObj.pm ... 开始失败......
如何让它发挥作用?
答案 0 :(得分:24)
放弃use
。严重。
use
告诉perl从另一个文件中读取代码,由于代码位于同一个文件中,因此您无需这样做。
答案 1 :(得分:14)
除非我试图创建一个没有人应该知道的私有包,否则我会为每个文件放一个包。这解决了这个问题。但是,让我们将它们放在同一个文件中。
use加载文件并调用该包中的import
方法。真的只是它的论证看起来像一个模块名称。它正在寻找文件。如果文件不存在,那就是barfs。
您可以执行此操作,其中BarObj
假定FooObj
已存在:
{
package FooObj;
sub new { bless { _count => 0 }, $_[0] }
sub add_data { $_[0]->{_count}++ }
}
{
package BarObj;
use Data::Dumper;
sub new {
bless { myFoo => FooObj->new }, $_[0];
}
sub foo { $_[0]->{myFoo} }
sub some_method { print Dumper( $_[0] ) }
}
my $bar = BarObj->new;
$bar->some_method;
如果你需要与一个包进行交互(这就是它的全部内容:不是一个模块或一个对象),你只需要在想要使用它之前定义它。如果您需要导入某些内容,可以直接致电import
:
FooObj->import( ... );
假设您要导入FooObj
的内容(但不是继承!),您可以直接调用import
而不加载;
{
package FooObj;
use Data::Dumper;
sub new { bless { _count => 0 }, $_[0] }
sub add_data { $_[0]->{_count}++ }
use Exporter qw(import);
our @EXPORT = qw(dumper);
sub dumper { print Dumper( $_[0] ) }
}
{
package BarObj;
FooObj->import;
sub new {
bless { myFoo => FooObj->new }, $_[0];
}
sub foo { $_[0]->{myFoo} }
# dumper mixin, not inherited.
sub some_method { dumper( $_[0] ) }
}
my $bar = BarObj->new;
$bar->some_method;
答案 2 :(得分:10)
按照惯例,我们将一个包放在一个文件中,并将它们命名为相同的东西,但这只是为了方便。您可以将多个包放在一个文件中。由于它们已经加载,因此您无需使用use
。
您也不需要为包创建特殊的范围,因为package关键字会处理它。使用大括号确实有助于our
变量的范围。所以你并不严格需要那些支撑块,但它们是个好主意。
use
使用包命名约定来查找要加载的相应文件。模块内的package
关键字定义命名空间。导入函数处理包加载(通常从Exporter继承)。
#!/usr/bin/perl
use strict;
use warnings;
package FooObj;
sub new
{
my $this = shift;
my $class = ref($this) || $this;
my $self = {};
bless $self, $class;
$self->initialize();
return $self;
}
sub initialize { }
sub add_data { }
package BarObj;
#use FooObj; <-- not needed.
sub new
{
my $this = shift;
my $class = ref($this) || $this;
my $self = { myFoo => FooObj->new() };
bless $self, $class;
$self->initialize();
return $self;
}
sub initialize { }
sub some_method { }
sub myFoo { return $_[0]->{myFoo} }
package main;
use Test::More;
my $bar = BarObj->new();
isa_ok( $bar, 'BarObj', "bar is a BarObj" );
isa_ok( $bar->myFoo, 'FooObj', "bar->myFoo is a FooObj" );
done_testing();
__DATA__
ok 1 - bar is a BarObj isa BarObj
ok 2 - bar->myFoo is a FooObj isa FooObj
1..2