我刚开始学习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
构造函数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)
以消除呼叫的歧义
您没有创建新对象,因此$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实际上是一个对象,而不仅仅是一个返回代码:)