这不是一个好主意。
Perl 使用use strict;
来处理这样的问题:
$employee_name = "Bob";
print "The name of the employee is $employeeName\n";
输入错误的变量名是一个常见问题。使用use strict;
强制你声明你的变量,所以这样的错误可以在编译时被捕获。
但是,散列键和散列引用删除了这种保护。因此:
my $employee[0] = {}
$employee[0]->{NAME} = "Bob";
print "The name of the employee is " . $employee[0]->{name} . "\n";
当你开始谈论复杂的数据结构时,使用对象的原因之一是为了防止这些类型的错误:
my $employee = Employee->new;
$employee->name("Bob");
print "The name of the employee is " . $employee->Name . "\n";
这个错误会被捕获,因为方法名是name
而不是Name
。
允许用户随意创建自己的方法会消除我们通过使用对象获得的保护:
my $employee = Employee->new;
$employee->name("Bob"); #Automatic Setter/Getter
print "The name of the employee is " . $employee->Name . "\n"; #Automatic Setter/Getter
现在,由于自动设置器和获取器,我们无法捕获错误,因为用户名的任何方法都是有效的——即使该用户犯了错误。
事实上,我设置了我的对象,所以我的对象不一定知道它的结构。foo
使用方法和观察以下类bar
:
sub new {
my $class = shift;
my $foo = shift;
my $bar = shift;
my $self = {};
bless $self, $class;
$self->foo($foo);
$self->bar($bar);
return $self;
}
sub foo {
my $self = shift;
my $foo = shift;
my $method_key = "FOO_FOO_FOO_BARRU";
if (defined $foo) {
$self->{$method_key} = $foo;
}
return $self->{$method_key};
}
sub bar {
my $self = shift;
my $bar = shift;
my $method_key = "BAR_BAR_BAR_BANNEL";
if (defined $bar) {
$self->{$method_key} = $bar;
}
return $self->{$method_key};
}
我可以在我的构造函数foo
中设置类值。bar
但是,我的构造函数不知道这些值是如何存储的。它只是创建对象并将其传递给我的 getter/setter 方法。我的两种方法也不知道它们如何存储彼此的值。这就是为什么我可以为我的方法的哈希键取如此疯狂的名称,因为这仅在方法中可用,而在其他任何地方都没有。
相反,我的方法foo
和bar
都是 setter 和 getter。如果我给他们一个foo
or的值bar
,则该值被设置。否则,我只是返回当前值。
但是,我相信您已经知道所有这些,并且会坚持必须这样做。很好...
处理您想要做的事情的一种方法是创建一个AUTOLOAD子例程。当没有同名的其他方法子例程时,自动调用 AUTOLOAD 子例程。$AUTOLOAD
包含调用的类和方法。您可以使用它来设置自己的值。
这是我的测试程序。我使用两种方法bar
和foo
,但我可以使用任何我喜欢的方法,它仍然可以正常工作
一项更改是,我在构造函数中使用参数散列而不是值列表。除了这被认为是现代方式之外没有真正的区别,我只想与其他人的做法保持一致。
另请注意,我将方法名称标准化为全小写。这样$object->Foo
,$object->foo
和$object-FOO
都是相同的方法。这样,我至少消除了大小写错误。
use strict;
use warnings;
use feature qw(say);
use Data::Dumper;
my $object = Foo->new({ -bar => "BAR_BAR",
-foo => "FOO_FOO",
}
);
say "Foo: " . $object->foo;
say "Bar: " . $object->bar;
$object->bar("barfu");
say "Bar: " . $object->bar;
say Dumper $object;
package Foo;
sub new {
my $class = shift;
my $param_ref = shift;
my $self = {};
bless $self, $class;
foreach my $key (keys %{$param_ref}) {
# May or may not be a leading dash or dashes: Remove them
(my $method = $key) =~ s/^-+//;
$self->{$method} = $param_ref->{$key};
}
return $self;
}
sub AUTOLOAD {
my $self = shift;
my $value = shift;
our $AUTOLOAD;
( my $method = lc $AUTOLOAD ) =~ s/.*:://;
if ($value) {
$self->{$method} = $value;
}
return $self->{$method};
}