ПРЕДИСЛОВИЕ:Пожалуйста, ради этого обсуждения, давайте на мгновение проигнорируем тот факт, что та же цель может быть достигнута с помощью Class::Accessor или даже просто с помощью Moose (, вероятно, с лучшими результатами при учете удобочитаемости и ремонтопригодности кода).
Что касается объектно-ориентированного Perl, в книге Programming Perl
обсуждается возможность создания методов доступа с замыканиями. Например, это допустимый фрагмент кода:
#!perl
use v5.12;
use warnings;
# at run-time
package Person1;
my @attributes = qw/name age address/;
for my $att ( @attributes )
{
my $accessor = __PACKAGE__. "::$att";
no strict 'refs'; # allow symbolic refs to typeglob
*$accessor = sub {
my $self = shift;
$self->{$att} = shift if @_;
return $self->{$att};
};
}
sub new { bless {}, shift }
package main;
use Data::Dumper;
my $dude = Person1->new;
$dude->name('Lebowski');
say Dumper($dude);
В приведенном выше примере, если я не ошибаюсь, класс составляется во время выполнения-, а его методы доступа создаются одновременно с созданием экземпляра класса.. Это означает, что при создании объекта будет штраф за скорость.
Теперь рассмотрим следующую альтернативу:
#!perl
use v5.12;
use warnings;
package Person2;
BEGIN
{
for my $att (qw/name age address/)
{
my $accessor = __PACKAGE__. "::$att";
no strict 'refs'; # allow symbolic refs to typeglob
*$accessor = sub {
my $self = shift;
$self->{$att} = shift if @_;
return $self->{$att};
};
}
}
sub new { bless {}, shift }
package main;
use Data::Dumper;
my $dude = Person2->new;
$dude->name('Lebowski');
say Dumper($dude);
В этой версии композиция создается внутри BEGIN
блока (, т. е. во время компиляции-), и я полагаю, что, решая эту задачу как как можно быстрее в жизненном-цикле программы, я экономлю время при создании объекта во время выполнения-.
Простое Benchmark
,
# benchmark it!
package main;
use Benchmark qw/cmpthese/;
cmpthese(-2, {
accessors_new => sub { Person1->new },
accessors_begin => sub { Person2->new },
});
по-видимому, подтверждает мою теорию этими результатами:
Rate accessors_begin accessors_new
accessors_begin 853234/s -- -9%
accessors_new 937924/s 10% --
Предполагая, что мои рассуждения до сих пор были правильными,
BEGIN
как на эффективный способ манипулирования классами такого рода?