【问题标题】:Why I cannot call a module's function after required or used successfully?为什么需要或成功使用后无法调用模块的功能?
【发布时间】:2013-09-02 22:17:58
【问题描述】:

我有一个名为genbank.pm 的Perl 模块文件,它有一个子程序new;这个 Perl 模块没有使用Exporter,也没有定义@EXPORT@EXPORT_OK。在同一个目录下我有一个名为test.pl的Perl文件,test.pl的代码是:

require 'genbank.pm';
use strict;
our $result = genbank::new();

当我使用 Komodo 运行它时,它会报告:

Undefined subroutine &genbank::new called at /home/mrs/scripts/test.pl line 3;

在我更改代码后

our $result = genbank::new();

our $result = genbank->new();

它说:

Can't locate object method "new" via package "genbank"(perhaps you forgot to load "genbank"?) at /home/mrs/scripts/test.pl line 3.

【问题讨论】:

  • 当您使用use genbank; 而不是require ... 时会发生什么?在genbank.pm 里面,顶部附近有package genbank; 声明吗?
  • 不,genbank.pm 中的包声明是“package MRS::Scripts::genbank”,它是文件 genbank.pm 中唯一的包声明。 .那么,下一步是什么?
  • 从“require ...”更改为“use ...”没有区别。
  • 在我将包声明从“package MRS::Scripts::genbank”更改为简单的“package genbank”之后,调用有效。所以,我的问题是,我该怎么做才能使调用成功,另一方面将包声明保留为“package MRS::Scripts::genbank”?
  • About perl "use" keyword的可能重复

标签: perl require perl-module subroutine


【解决方案1】:

您没有提供足够的信息来完全确定该问题,但最可能的原因是 new 子位于 genbank 以外的包中。

当您尝试调用genbank::new(或genbank->new)时,Perl 在包genbank 中查找名为new 的子,不在文件genbank.pm。按照惯例,文件genbank.pm 将包含一个名为genbank 的包,但这纯粹是为了约定和方便。它由语言强制执行,并且文件名和包名之间绝对没有自动连接。

要了解您的潜艇被放置在哪个包中,请查看genbank.pm 中是否有任何行显示package xxxx;sub new 行之前出现的最后一个将告诉您new 所属的包。如果定义前没有package 语句,则默认在包main 中。

(如果您负责genbank.pm源代码,我还建议将package genbank;添加到文件中或重命名文件以匹配它实际包含的包,以避免在未来。)

根据 OP 的评论进行编辑:

由于模块当前以package MRS::Scripts::genbank 开头,那么这就是创建new 子的包。调用它有两种选择:

  1. 将其称为MRS::Scripts::genbank::new(或者,如果它实际上是一个对象构造函数,则称为MRS::Scripts::genbank->new)。如果你想使用包名来调用它,那么你必须使用正确的包名。

  2. MRS::Scripts::genbank 包中导出它并修改调用脚本以从该包中导入符号(将genbank.pm 移动到MRS/Scripts/genbank.pm 并将require 更改为use MRS::Scripts::genbank; 通过在require 之后添加MRS::Scripts::genbank->import;),然后将其称为new()。虽然这将在您的问题的有限范围内起作用,但我建议强烈反对它,因为一旦您对另一个包含 sub new 的模块重复此操作,它就会崩溃,因为可以不要同时在同一个地方成为两个news。

解决此问题的最简单方法是将genbank.pm 移动到MRS/Scripts/genbank.pm,将require 更改为require MRS::Scripts::genbank.pm(或use;如果您不导出任何内容,它们是等效的),然后将子称为MRS::Scripts::genbank::newMRS::Scripts::genbank->new。这种方法将使文件名和包名彼此同步,这将使将来需要维护代码的人(可能是你......)的生活更轻松。

【讨论】:

  • 是的,包声明是“package MRS::Scripts::genbank”。这个声明位于文件 genbank.pm 的第一行,它是唯一的包声明。所以,我该怎么办下一个?
  • 在我将包声明从“package MRS::Scripts::genbank”更改为简单的“package genbank”之后,调用有效。所以,我的问题是,我该怎么做才能使调用成功,另一方面将包声明保留为“package MRS::Scripts::genbank”?
  • @Vico_Wu 鉴于您评论中的其他信息,我已经编辑了我的答案以解释如何完成这项工作。
  • require MRS::Scripts::genbankrequire 'MRS/Scripts/genbank.pm'
猜你喜欢
  • 2017-03-19
  • 1970-01-01
  • 2020-04-04
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
  • 2018-10-06
  • 1970-01-01
  • 2021-12-18
相关资源
最近更新 更多