所以我想知道Perl类方法和标准模块中的普通子例程之间的使用是否有任何差异。你有没有时间使用其中一个?对于这个例子,我假设在任一模块中都没有对象方法。
这里快速的小主要课程:
#!/usr/local/bin/perl
use strict;
use warnings;
use Foo;
use Bar;
my $arg1 = "blah";
my ($str1, $str2);
$str1 = Foo::subroutine($arg1);
$str2 = Bar->subroutine($arg1);
exit(0);
Package Foo将保持我的普通子程序调用
use strict;
use warnings;
package Foo;
sub subroutine {
my $arg = shift;
my $string = "Ordinary subroutine arg is $arg\n";
return $string;
}
1;
包栏会保存我的类方法调用
use strict;
use warnings;
package Bar;
sub subroutine {
my $class = shift;
my $arg = shift;
my $string = "Class method arg is $arg\n";
return $string;
}
1;
通常,如果我正在编写Perl代码,我只会使用类方法选项(就像使用Bar示例一样),但是在阅读了一位使用类似语法的前同事的代码后,我开始思考这个问题。 Foo的例子。两者似乎本身都做同样的事情,但似乎不仅仅是满足于眼睛。
答案 0 :(得分:4)
决策者是你的Module
是否是面向对象的模块。
如果Module
只是一个子程序集合的容器,那么我希望它使用Exporter
并提供将其子程序的子集导入调用名称空间的机会。一个例子是List::Util
另一方面,如果有一个构造函数Module::new
,并且打算以OO方式使用它,那么你就不应该将简单的子程序与方法混合在一起(除了对于模块在内部使用的私有子例程。一个例子是LWP::UserAgent
所以我希望这些来源可以像其中一个或另一个一样写出来,而不是两者之间的混合。当然,在某些情况下应该忽略经验法则,但在这种情况下没有任何想法。
<强> Foo.pm 强>
use strict;
use warnings;
package Foo;
use Exporter 'import';
our @EXPORT_OK = qw/ subroutine /;
sub subroutine {
my ($arg) = @_;
"Ordinary subroutine arg is $arg\n";
}
1;
<强> Bar.pm 强>
use strict;
use warnings;
package Bar;
sub new {
my $class = shift;
bless {}, $class;
}
sub subroutine {
my $class = shift;
my ($arg) = @_;
"Class method arg is $arg\n";
}
1;
<强> main.pl 强>
#!/usr/local/bin/perl
use strict;
use warnings;
use Foo 'subroutine';
use Bar;
my $arg1 = "blah";
print subroutine($arg1);
print Bar->subroutine($arg1);
<强>输出强>
Ordinary subroutine arg is blah
Class method arg is blah
答案 1 :(得分:2)
普通子程序没有任何内在错误。他们做了他们设计得很好的事情。
另一方面,方法和完全可以与任何继承自你的类完美搭配。
所以问问自己:
或
这两个世界都有足够的空间,但是如果你发现自己,就像你在Bar
中所做的那样,在整个模块中忽略$class
(或者更常见的是$self
),那么也许你把它们设计成方法已经走得太远了。更重要的是,当你的方法无法区分这两个类别时,任何试图从你的边缘OO“级别”继承的人都会得到一个粗鲁的惊喜......
答案 2 :(得分:1)
这更像是一个代码范例的问题。
对于代码,非面向对象的方法绝对没有问题。它有效,而且效果很好。
然而,面向对象提供了一系列值得考虑的好处 - 如果它们是你想要的东西,那就去做OO路线吧。
具体而言 - 对象提供封装。这使我更容易编写模块而你只需使用它。比如说LWP::UserAgent
为例:
require LWP::UserAgent;
my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->env_proxy;
$ua->agent('Mozilla/5.0');
my $response = $ua->get('http://search.cpan.org/');
if ($response->is_success) {
print $response->decoded_content; # or whatever
}
else {
die $response->status_line;
}
现在,上面的所有都可以通过继承的子例程来完成。但是如果你想对多个页面进行多次提取,你要么必须: