如果perlcritic
说“没有子回报是错误的”,如果真的不需要它们会有什么选择呢?
我养成了两个显然不好的习惯:
例如,我可能会......
#!/usr/bin/perl
use strict;
use warnings;
@main::array = (1,4,2,6,1,8,5,5,2);
&sort_array;
&push_array;
&pop_array;
sub sort_array{
@main::array = sort @main::array;
for (@main::array){
print "$_\n";
}
}
sub push_array{
for ( 1 .. 9 ){
push @main::array, $_;
}
}
sub pop_array {
for ( 1 .. 3 ){
pop @main::array;
}
}
我不是一直这样做的。但在上面,它是有道理的,因为我可以隔离操作,而不必担心来回传递值,它通常看起来很整洁。
但正如我所说,perl评论家说错了 - 因为没有回报......
那么,是否有人能够解释我正在尝试做的事情并建议在perl中采用这种编码方式的更好方法?例如。我有点做OOP吗?
答案 0 :(得分:6)
简而言之 - 是的,你基本上都在做OO,但这种方式会让所有人感到困惑。
做这样的潜艇的危险在于你在远处行动。这是一个糟糕的编码风格,必须完全看看其他地方可能会破坏您的代码。
这通常是为什么'全局'尽可能避免使用。
对于一个简短的剧本来说,太多并不重要。
关于返回值 - 默认情况下,Perl返回最后一个表达式的结果。 (见:return
)
(如果没有显式返回,子例程,eval或do FILE会自动返回最后一个表达式的值。)
Perl critic标记的原因是:
要求所有子程序使用以下方法之一显式终止:return,carp,croak,die,exec,exit,goto或throw。
在其末尾没有显式返回语句的子例程可能会令人困惑。推断返回值将是多么具有挑战性。
此外,如果程序员并不意味着存在重要的返回值,并且省略了return语句,则某些子程序的内部数据可能泄漏到外部。
Perlcritic并不总是正确的 - 如果有充分理由做你正在做的事情,那就把它关掉。只要您已经考虑过并且意识到风险会产生影响。
就我个人而言,我认为明确返回某些内容的风格更好,即使它只是return;
。
无论如何,以(原始)OO方式重新绘制代码:
#!/usr/bin/perl
use strict;
use warnings;
package MyArray;
my $default_array = [ 1,4,2,6,1,8,5,5,2 ];
sub new {
my ( $class ) = @_;
my $self = {};
$self -> {myarray} = $default_array;
bless ( $self, $class );
return $self;
}
sub get_array {
my ( $self ) = @_;
return ( $self -> {myarray} );
}
sub sort_array{
my ( $self ) = @_;
@{ $self -> {myarray} } = sort ( @{ $self -> {myarray} } );
for ( @{ $self -> {myarray} } ) {
print $_,"\n";
}
return 1;
}
sub push_array{
my ( $self ) = @_;
for ( 1 .. 9 ){
push @{$self -> {myarray}}, $_;
}
return 1;
}
sub pop_array {
my ( $self ) = @_;
for ( 1 .. 3 ){
pop @{$self -> {myarray}};
}
return 1;
}
1;
然后用:
来调用它#!/usr/bin/perl
use strict;
use warnings;
use MyArray;
my $array = MyArray -> new();
print "Started:\n";
print join (",", @{ $array -> get_array()} ),"\n";
print "Reshuffling:\n";
$array -> sort_array();
$array -> push_array();
$array -> pop_array();
print "Finished:\n";
print join (",", @{ $array -> get_array()} ),"\n";
它可能有点整理,但希望这说明 - 在你的对象中,你有一个内部阵列'然后你用'打电话。
结果大致相同(我认为我已经复制了逻辑,但完全不相信!)但你有一个自给自足的事情。
答案 1 :(得分:1)
如果该功能并不意味着返回任何内容,则无需使用return
!
不,您不使用OO的任何方面(封装,多态等)。你在做什么叫做程序编程。没有错。我在核电站的所有工作都是以这种方式编写的。
问题是使用@main::array
,我不是说你可以将其缩写为@::array
。完全限定的名称可以逃避严格的检查,因此它们更容易出错。 Mistyped var name不会被轻易捕获,并且使用相同的变量名很容易让两段代码发生碰撞。
如果您只使用一个文件,则可以使用my @array
,但我认为您正在使用@main::array
,因为您正在从多个文件/模块访问它。我建议将our @array
放在模块中,然后将其导出。
package MyData;
use Exporter qw( import );
our @EXPORT = qw( @array );
our @array;
1;
在变量名中有一些提示(例如前缀或后缀),表明这是一个在许多模块中使用的变量,这样会很好。
顺便说一句,如果你想创建一个对象,它看起来像
package MyArray;
sub new {
my $class = shift;
my $self = bless({}, $class);
$self->{array} = [ @_ ];
return $self;
}
sub get_elements {
my ($self) = @_;
return @{ $self->{array} };
}
sub sort {
my ($self) = @_;
@{ $self->{array} } = sort @{ $self->{array} };
}
sub push {
my $self = shift;
push @{ $self->{array} }, @_;
}
sub pop {
my ($self, $n) = @_;
return splice(@{ $self->{array} }, 0, $n//1);
}
my $array = MyArray->new(1,4,2,6,1,8,5,5,2);
$array->sort;
print("$_\n") for $array->get_elements();
$array->push_array(1..9);
$array->pop_array(3);
我改进了你的界面。 (排序不应该打印。推送不同的东西并弹出除三个元素之外的东西会很好。)