使用模块中没有包装的符号(要求)

时间:2014-02-20 17:42:34

标签: perl perl-module

我已经问了一个类似的问题,但它更多地与使用裸字功能有关。基本上,我正在重构我的一些代码,因为我已经开始在perl中学习“package”和OOP。由于我的模块都没有使用“软件包”,所以我可以将它们“需要”到我的代码中,并且我能够毫无困难地使用它们的变量和函数。但是现在我创建了一个模块,我将其用作对象操作的类,我希望能够以相同的方式继续在其他模块中使用我的函数。没有多少阅读文档和教程已经完全回答了我的问题,所以,如果有人可以提供有关它如何工作的解释,以及为什么,那将会有很长的路要走,不仅仅是“这就是你如何做” - 类型答案。

也许这可以说明问题:

myfile.cgi:

require 'common.pm'
&func_c('hi');
print $done;

common.pm:

$done = "bye";
sub func_c {print @_;}
按预期,

将打印“hi”然后“bye”。

myfile_obj.cgi:

use common_obj;
&func_obj('hi');
&finish;

common_obj.pm:

package common_obj;
require 'common.pm';
sub func_obj {&func_c(@_);}
sub finish {print $done;}

给出“Undefined subroutine func_c ...”

我知道(有点)关于命名空间等等,但我不知道如何实现我想要的结果(让func_obj能够从common.pm调用func_c)而不必修改common.pm (这可能会打破一堆依赖于它的其他模块和脚本的工作方式)。我知道在BEGIN中使用被称为“require”及其import()..但同样,这需要修改common.pm。我想要完成的是什么?

3 个答案:

答案 0 :(得分:2)

您需要导出来自包common_obj的符号(它不是现有的类包)。

您需要熟悉Exporter模块。 Modern Perl也有介绍(免费提供书籍,但也考虑购买)。

这很简单 - 如果你在@EXPORT_OK列出功能,那么use你的包裹可以使用它们。您还可以通过EXPORT_TAGS将功能组合到命名组中。

首先导出几个函数,列出use语句中的函数并获取基础知识。这很容易。

如果您的模块确实是面向对象的,那么您将通过对象引用$my_obj->some_method(123)访问这些方法,因此无需导出。一个软件包甚至可以提供过程/功能和面向对象的接口。

你想要用旧的东西包装旧的“不安全”模块似乎是一种合理的方式来继续前进。在不破坏现有工作代码的情况下控制事物。


编辑:解释。

如果您需要一段不合格的代码,那么它的定义将最终出现在需求包(common_obj)中,但如果您将代码限制在包定义中,然后use,则需要显式导出定义。

答案 1 :(得分:1)

您可以使用common_obj :: func_obj和common_obj :: finish。您只需添加其命名空间即可。你不需要'&'在这种情况下。

当您使用package语句(在common_obj.pm中)时,您更改了后续函数的命名空间。如果没有(在common.pm中),则将函数包含在同一名称空间(main或common_obj)中。我不相信这与use / require有任何关系。

您应该使用Exporter。将common_obj更改为添加:

use base Exporter;
@EXPORT_OK = qw/func_obj finish/;

然后更改myfile_obj:

use common_obj qw/func_obj finish/;

我假设您只是尝试将新界面添加到旧的“正常工作”模块中。我确信这充满了问题,但如果可以做到这就是一种方法。

答案 2 :(得分:1)

您正在努力使用套餐,因为这将在未来为您提供很多帮助。为了实现这一目标,我建议您也开始重构旧代码。我可以理解不想触及任何旧的cgi文件,并且现在同意这个选择。但是您需要编辑一些包含的模块以获得您想要的位置。

使用您的示例作为基线,目标是保留myfile.cgi和所有类似的文件,而不做任何更改,但其他一切都是公平的游戏。

步骤1 - 创建一个新包,以包含common.pm

中的函数和变量

common.pm需要是一个包,但是如果不影响你的旧代码就无法实现。解决方法是创建一个全新的包来包含旧文件中的所有函数和变量。这也是为所有当前和将要创建的包创建更好的命名约定的好机会。我假设你可能没有将它命名为common.pm,但无论如何,你应该选择一个目录并命名你的项目。我将为以前在common.pm

中保存的函数和变量随机选择名称MyProject :: Core
package MyProject::Core;

@EXPORT = qw();
@EXPORT_OK = qw($done func_c);
%EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]);

use strict;
use warnings;

our $done = "bye";

sub func_c {
    print @_, "\n";
}

1;

__END__

这个新包应该放在MyProject / Core.pm中。您需要在EXPORT_OK列表中包含要导出的所有变量和函数。另外,作为一个小注释,我在示例中为所有打印语句添加了返回字符,以便于测试。

其次,编辑common.pm文件以包含以下内容:

use MyProject::Core qw(:all);

1;

__END__

你的myfile.cgi应该像现在一样工作。在继续之前确认这一点。

接下来,您可以开始创建新的包,这些包将依赖于旧的common.pm中的函数和变量。您的示例common_obj.pm可以重新编码为以下内容:

package common_obj;

use MyProject::Core qw($done func_c);

use base Exporter;
@EXPORT_OK = qw(func_obj finish);

use strict;
use warnings;

sub func_obj {func_c(@_);}
sub finish {print "$done\n";}

1;

__END__

最后,myfile_obj.cgi被重新编码为so:

use common_obj qw(func_obj finish);

use strict;
use warnings;

func_obj('hi');
finish();

1;

__END__

现在,我可以使用@EXPORT代替@EXPORT_OK来自动导出所有可用的函数和变量,但更好的做法是只选择性地导入您实际需要的那些函数。此方法还使您的代码更加自我记录,因此有人查看任何文件,可以搜索以查看特定函数的来源。

希望这有助于您开始更好的编码实践。重构旧代码可能需要很长时间,但是不断更新技能和工具绝对值得一提。