ПРИМЕЧАНИЕ ВПЕРЕД: Пожалуйста, ради этого обсуждения давайте на мгновение проигнорируем тот факт, что тот же самый конец может быть достигнут при обращении к 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
в качестве эффективного способа выполнения такого рода манипуляций с классами? - Когда этоне рекомендуется?