Наследование атрибутов класса Perl - PullRequest
0 голосов
/ 19 мая 2018

У меня есть атрибут класса, например, счетчик созданных объектов в некотором базовом классе,

package A;
our $counter = Counter->new; # not just a counter in fact, so initialization code should be inherited by descendants as well

sub new {
    $counter++;
    bless {}
}
sub get_counter {
    $counter
}

package B;
use base 'A';

package main;
B->get_counter();

Я хочу, чтобы пакет B имел свою собственную копию этого атрибута класса (например, считая объекты только класса B), и все унаследованные методы из пакета A должны иметь дело с этой копией.Как правильно реализовать это на обычном Perl и в Moo / Moose?Похоже, MooX :: ClassAttribute не может быть унаследован.Одно из уродливых решений - повторить код инициализации атрибута в каждом потомке и использовать символическую разыменование, например, $ {"$ {class} :: counter"} в методах предка, чтобы получить доступ к этому атрибуту с фактическим именем пакета.Но, похоже, должен быть более элегантный способ.

1 Ответ

0 голосов
/ 19 мая 2018

Модель объекта Perl по умолчанию не имеет понятия атрибутов класса.И нет такого рода хуков, как «когда создается новый подкласс, запустите этот код».

Вместо этого базовый класс может поддерживать хэш счетчиков, используя имя класса в качестве ключей:

package A;
my %counters;

sub new {
  my ($class) = @_;
  my $counter = $counters{$class} //= Counter->new;
  $counter++;
  return bless {} => $class;
}

sub get_counter {
  my ($self_or_class) = @_;
  my $class = (ref $self_or_class) || $self_or_class;
  $counters{$class};
}

package B;
use parent -norequire, 'A';

Это создаст новый счетчик при создании экземпляра подкласса.Обратите внимание, что первым аргументом метода является либо имя класса, либо экземпляр объекта.Нам нужно использовать это в new() в качестве хеш-ключа.В get_counter() я написал это так, что метод может быть вызван как для класса, так и для объекта с одинаковым эффектом.

Подобный метод известен как объекты наизнанку, где хранится объектполя в хеше, хранящемся в классе, так что сам объект не содержит никаких данных.

(Почему parent вместо base? Модуль parent только наследует, тогда как base также интегрируется с fields прагмой, которую вы не должны использовать.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...