每当您将标量数据以外的内容存储到 Perl 变量中时,您应该开始考虑面向对象的 Perl。
看看Perl Object Oriented Tutorial。
我将在这里对您进行所有面向对象的操作:
#! /usr/bin/env perl
use strict;
use warnings;
my %list;
my $list{1} = Widget->new("first", 2);
my $list{2} = Widget->new("second", 3);
my $i = "2";
check_something( $list{$i} );
哇!我在做什么很明显。我有一个名为的散列%list
,其中包含小部件的对象!我的check_somthing
子程序正在使用一个 Widget 对象。它应该$list{$i}
作为论据。
但是小部件是什么样的:
package Widget;
sub new {
my $class = shift;
my $self = shift;
my $name = shift;
my $quantity = shift;
my $self = {};
bless $self, $class;
$self->Name($name) if defined $name;
$self->Quantity($quantity) if defined $quantity;
return $self;
}
sub name {
my $self = shift;
my $name = shift;
if ( defined $name ) {
$self->{name} = $name;
}
return $self->{name};
}
sub Quantity {
my $self = shift;
my $quanity = shift;
if ( defined $quanity ) {
$self->{quantity} = $quantity;
}
return $self->{quantity};
}
这很简单。通过使用对象而不是散列的散列,我简化了我的逻辑。很容易看出我想要传递给我的子程序的是一个 Widget 对象。事实上,check_somthing
子程序可能是另一种方法:
sub check_something {
my $widget = shift;
my $name = $widget->Name;
my $quanity = $widget->Quantity;
# Here be dragons...
return ???
}
现在,我的代码如下所示:
#! /usr/bin/env perl
use strict;
use warnings;
my %list;
my $list{1} = Widget->new("first", 2);
my $list{2} = Widget->new("second", 3);
my $i = "2";
$list{$i}->check_something;
请注意,这做了很多可以改进您的代码的事情:
- 首先,它清理了您的逻辑。您没有传递列表的散列或散列或一些难以理解的结构,在您放弃并在这里提出问题之前,您可能浪费了两到三个小时试图弄清楚。(没有犯罪。我自己去过那里并做过)。相反,您传递的是一个易于理解的对象。
- 其次,它确保您的
check_something
子程序只能由 Widgets 使用。如果您尝试将非 Widget 对象传递给check_something
,它将失败。更好的是,我可以Wooble
用它自己的check_something
子例程调用另一个对象,Perl 会找出我真正检查的内容。
例如:
my $widget = Widget->new("first", 2);
my $wooble = Wooble->new(1, "slam");
$widget->check_something;
$wooble->check_something;
Widget 和 Wooble 有自己的check_something
方法,而 Perl,因为它知道哪个对象是Widget,哪个对象是Wooble知道check_something
我应该运行哪个。
- 最后,
use strict;
不再破碎。use strict;
编译指示捕获了 90% 的错误。但是,当您通过从原始代码中剔除这些复杂结构来创建这些复杂结构时,您最终可能会同时创建use strict;
可以捕获但不能捕获的错误:
例如:
%list = (
1 => {name => 'first', quantity => 2},
2 => {name => 'second', quanity => 3}
);
你看到错误了吗?我用过quantity
一个,但后来拼错quanity
了另一个。这种类型的错误不会被编译器捕获。然而:
$list{1} = Widget->new;
$list{1}->name('first');
$list{1}->quantity(2);
$list{2} = Widget->new;
$list{2}->name('second');
$list{2}->quanity(3); #Compiler Error!
现在,Perl 编译器会捕捉到我的错误,因为quanity
它不仅是哈希引用的键,而且是一个不存在的子例程。
其他人已经给了你技术上正确的答案,但如果你经常使用复杂的数据结构,如散列散列或列表散列,或散列列表,是时候开始使用对象了。一旦你习惯了它们,你会发现你可以更快地编码,更少的挫败感和更少的逻辑问题。