如何调用我在同一个文件中定义的Perl包?

时间:2010-04-12 10:14:05

标签: perl oop

我需要定义一些模块并在同一个文件中使用它们。不,我不能改变要求。

我想做以下事情:

{
    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 ...   开始失败......

如何让它发挥作用?

3 个答案:

答案 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