使用变量引用模块时遇到问题,似乎搞乱了变量的传递:
package TOTO;
use Data::Dumper;
sub print {
print Dumper(@_);
}
package main;
TOTO::print('Hello World');
print ">>>>>>>>>>>\n";
my $package = 'TOTO';
$package->print('Hello World');
输出是:
$VAR1 = 'Hello World';
>>>>>>>>>>>
$VAR1 = 'TOTO';
$VAR2 = 'Hello World';
关于如何避免将TOTO
作为第一个变量传递的任何建议?
答案 0 :(得分:2)
简短:观察到的行为来自于在包名上使用->
。
箭头运算符与引用或对象一起使用,该对象本身是对已经bless
的数据结构的引用。 (或者使用类名,见下文。)该对象或类名作为第一个参数安静地传递,以便整个系统可以工作。请注意,问题中的包不定义一个类(无法使用它创建对象)。
“ - >”是一个中缀解除引用运算符,就像在C和C ++中一样。如果右侧是[...],{...}或(...)下标,则左侧必须是对数组,散列或子例程的硬引用或符号引用分别。 (或者从技术上讲,一个能够持有硬引用的位置,如果它是用于赋值的数组或哈希引用。)请参阅perlreftut和perlref。
继续,对这个问题直接感兴趣的陈述
否则,右侧是方法名称或包含方法名称或子程序引用的简单标量变量,左侧必须是对象(有福的引用)或类名称(即,包裹名字)。请参阅perlobj。
因此,在与类相关的用法中,左侧可能包含类名,然后可以在其上调用类方法(或者可以只查询它)。鉴于一个类是一个包,那么这个是一个包名。
问题中的情况属于此范围,因此包名称将传递给子例程。但是,根据上面的引用,似乎sub只能是方法,这不是这里的情况。所以可能真的不允许->
使用pacakge TOTO;
use Exporter;
our (@ISA, @EXPORT_OK);
@ISA = ('Exporter');
@EXPORT_OK = qw(prn); # This can be asked for by user of package
use Data::Dumper;
sub prn {
print Dumper(@_);
}
1; # important for 'require' when this is used
。无论哪种方式,在非类别的包装上使用它都会让我觉得错误。
更新澄清。这个用途旨在解决加载包的模糊性。包名称保存到变量中,然后使用箭头操作符在其上调用子包。在这种情况下,必须将代码添加到sub中以处理第一个参数(包名称),无论调用如何,都通过箭头操作符提供。但是,当在一个对象上调用 时,我们必须允许一个案例,最后是一个涵盖两个不同用途的代码。我认为最好换成不涉及所有这些的设计。
如果你想使用一个包,比如作为一个库
档案TOTO.pm
prn
我已将子名更改为use warnings;
use strict;
use TOTO qw(prn);
prn("Hello World");
,因此它不是Perl库函数。主要脚本
TOTO::prn()
始终可以使用完全限定名TOTO
。如果你想把它变成一个需要在包中多一点的类。
此软件包@EXPORT_OK
默认情况下不会导出任何内容,除非要求。这就是main::
设置的原因,这就是我们需要在use TOTO
时列出要导入 <receiver android:name="ir.hamgam.fion.ec.mobile.services.BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
的函数的原因。例如,使用perlmod
答案 1 :(得分:2)
用最简单的术语来说,要创建面向对象的TOTO
模块,您必须创建一个至少包含构造函数子例程TOTO.pm
new
。
package TOTO;
sub new {
bless {};
}
sub print {
print "I am a TOTO object\n";
}
1;
该代码必须保存在名为TOTO.pm
的文件中,该文件必须与来源中的package TOTO
名称匹配
然后你可以编写一个使用该模块的程序,比如main.pl
。例如
use strict;
use warnings 'all';
use TOTO;
my $object = TOTO->new;
$object->print;
然后你创建了一个新的TOTO
对象来说明它是什么
如果我跑
$ perl main.pl
我得到了输出
I am a TOTO object
您将希望使此代码更有用,并且此主题有许多变体,但这些是基础知识
答案 2 :(得分:1)
这就是Perl的包装系统的运作方式。您需要在被调用的子中自己处理。您无法在通话前更改它。
sub print {
# special variable __PACKAGE__ contains "TOTO"
if ($_[0] eq __PACKAGE__ || ref $_[0] eq __PACKAGE__){
shift; # throw away class/object
}
print Dumper(@_);
}
ref $_[0]
部分在技术上是不需要的,因为你的班级中没有构造函数(你只在类上调用方法,但如果你在类中调用方法,它会做正确的事情,如果你曾经使用对象而不必在以后改变任何东西。)
答案 3 :(得分:1)
这是问题
关于如何避免将TOTO作为第一个变量传递的任何建议?
你自己发现了答案。这很好用
TOTO::print('Hello World');
如果您将其称为
TOTO->print('Hello World');
然后您要求perl将print
作为类方法调用,并将('TOTO', 'Hello World')
作为参数传递给TOTO::print
子例程
如果TOTO
只是一堆子程序,那么就像你找到的那样,只需致电TOTO::totosub
答案 4 :(得分:0)
检查之间的差异:
TOTO::print("Hello World");
和
TOTO->print("Hello World");
这不是正确的对象表示法,因为TOTO
只是一个字符串。
语法object->function(arguments)
whil传递object
作为第一个参数,存储为$this
,用于样本。
sub print {
my $this = shift @_;
print Dumper(@_);
}
可以完成这项工作(即使不是受祝福的对象)。
试试这个:
package TOTO;
use Data::Dumper;
sub new { return bless {}, shift; }
sub print {
my $self = shift @_;
if ( scalar $self =~ /=HASH\(/ ) {
print Dumper(@_);
} else {
print Dumper($self);
}
}
package main;
my $package = TOTO->new();
$package->print("Hello World");
TOTO::print("Hello World");
这可以输出:
$VAR1 = 'Hello World';
$VAR1 = 'Hello World';
并查看man perlobj
,man perlootut
和man perlmodlib