无法通过包“1”找到对象方法“say_hello”

时间:2017-01-05 11:13:04

标签: linux perl oop

我刚开始学习Perl。当我移动到面向对象时,我收到类似

的错误
Can't locate object method "say_hello" via package "1" (perhaps you forgot to load "1"?) at ./main.pl line 8.

我搜索了很多解决方案。遇到类似this的类似问题。我的理解是,这不是一般问题。

这是我的班级

# MyModule.pm

package MyModule;
use strict;
use warnings;

sub new {
    print "calling constructor\n";
}

sub say_hello {
    print "Hello from MyModule\n";
}

1;

这是我的测试脚本

# main.pl

#!/usr/bin/perl -w
use strict;
use warnings;

use MyModule;

my $myObj = new MyModule();
$myObj->say_hello();

如果从main.pl

中移除最后一行,代码工作正常

2 个答案:

答案 0 :(得分:8)

您的构造函数new需要将祝福引用返回到您用来包含对象信息的数据结构。您在此处没有相关数据,但仍需要返回

bless将数据与特定包相关联。在这种情况下,您的对象应该被祝福MyModule,以便perl在看到MyModule::say_hello等方法调用时知道查找$myObj->say_hello()

您当前的构造函数返回print语句返回的值,如果成功则返回1,因为它几乎可以肯定。这就是您在错误消息

中看到"1"的原因
  

找不到对象方法" say_hello"通过包" 1" (也许你忘了在./main.pl第8行加载" 1"?)。

对象数据的最常见容器是哈希,因此您需要将new更改为此

sub new {

    print "calling constructor\n";

    my $self = { };
    bless $self, 'MyModule';
    return $self;
}

然后你的程序将按预期工作。它创建一个匿名哈希并将其分配给$self变量,然后祝福并返回它

请注意,这可以更加简洁:

  • 如果没有return语句,子程序将返回最近执行的语句的值

  • 默认情况下,bless会将数据保存到当前包中

  • 在祝福之前无需将参考存储在变量中

因此,写作

可以达到同样的效果
sub new {

    print "calling constructor\n";

    bless { };
}

还请注意您的电话

my $myObj = new MyModule()

不太理想。它被称为间接对象表示法,可能不明确。最好始终使用直接方法引用,例如

my $myObj = MyModule->new()

以消除呼叫的歧义

答案 1 :(得分:5)

您没有创建新对象,因此$myObj只是“print”语句(或1)的返回代码。

您需要bless某些内容并将其返回。

sub new { 
   my ( $class ) = @_;
   print "Calling Constructor\n";
   my $self = {};
   bless $self, $class;
   return $self;
 }

那样$myObj实际上是一个对象,而不仅仅是一个返回码:)