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

Rob*_*nes 18 oop perl

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

我想做类似以下的事情:

{
    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();
Run Code Online (Sandbox Code Playgroud)

但是,这会产生以下消息:

无法在@INC中找到FooObj.pm ...
BEGIN失败了......

我如何让它工作?

Dav*_*man 24

掉下来use.认真.

use 告诉perl从另一个文件中读取代码,您不需要这样做,因为代码在同一个文件中.


bri*_*foy 14

除非我试图创建一个没有人应该知道的私有包,否则我会为每个文件放一个包.这解决了这个问题.但是,让我们把它们放在同一个文件中.

用法加载文件并调用该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;
Run Code Online (Sandbox Code Playgroud)

如果你需要与一个包进行交互(这就是它的全部内容:不是模块或对象),你只需要在想要使用它之前定义它.如果您需要导入某些内容,可以import直接调用:

FooObj->import( ... );
Run Code Online (Sandbox Code Playgroud)

假设有一些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;
Run Code Online (Sandbox Code Playgroud)


spa*_*azm 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
Run Code Online (Sandbox Code Playgroud)

  • 它不仅清晰,而且是一个范围问题.包没有创建一个范围,所以你在那里的my()变量是文件作用域,没有大括号会限制它. (6认同)
  • +1对于有趣的信息,我仍然更喜欢使用大括号,因为我认为它增加了视觉清晰度. (2认同)