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

sha*_*eeq 0 linux oop perl

我刚开始学习Perl.当我移动到面向对象时,我得到一个错误

Can't locate object method "say_hello" via package "1" (perhaps you forgot to load "1"?) at ./main.pl line 8.
Run Code Online (Sandbox Code Playgroud)

我搜索了很多解决方案.有像一些类似的问题,.我的理解是它不是一般问题.

这是我的课

# MyModule.pm

package MyModule;
use strict;
use warnings;

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

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

1;
Run Code Online (Sandbox Code Playgroud)

这是我的测试脚本

# main.pl

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

use MyModule;

my $myObj = new MyModule();
$myObj->say_hello();
Run Code Online (Sandbox Code Playgroud)

如果删除最后一行,代码工作正常 main.pl

Bor*_*din 8

构造函数new需要返回对用于包含对象信息的数据结构的祝福引用.这里没有相关数据,但您仍需要返回一些内容

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

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

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

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

sub new {

    print "calling constructor\n";

    my $self = { };
    bless $self, 'MyModule';
    return $self;
}
Run Code Online (Sandbox Code Playgroud)

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

请注意,这可以更简洁:

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

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

  • 在祝福之前,无需将引用存储在变量中

因此,写作可以达到同样的效果

sub new {

    print "calling constructor\n";

    bless { };
}
Run Code Online (Sandbox Code Playgroud)

还要注意你的电话

my $myObj = new MyModule()
Run Code Online (Sandbox Code Playgroud)

不太理想.它被称为间接对象​​表示法,可能含糊不清.最好始终使用直接方法引用,例如

my $myObj = MyModule->new()
Run Code Online (Sandbox Code Playgroud)

以消除呼叫的歧义


Sob*_*que 5

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

你需要bless 一些东西然后归还它.

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

这种方式$myObj实际上是一个对象,而不仅仅是一个返回代码:)