Когда я должен сделать класс Moose неизменным, когда я на самом деле использую -> meta? - PullRequest
5 голосов
/ 28 марта 2011

Обычно я заканчиваю класс при компиляции через __PACKAGE__->meta->make_immutable в конце класса.Тем не менее, когда я должен сделать неизменяемый класс, который будет составлять роли во время выполнения?Должен ли я делать это, чтобы улучшить производительность или это несовместимо с make_immutable?make_immutable, кажется, ускоряет создание объекта, но делает ли он что-нибудь после создания объекта?

Например, что-то вроде:

BUILD {
  my $self = shift;
  use Module::Load;

  ### Use the arguments passed in to determine roles applicable to 
  ### this instance of the object. Load and apply roles.
  for my $role ($self->_determine_roles()) { 
    load $role;
    $role->meta->apply($self);
  }

  ### $self is now a Class::MOP::Class::__ANON__... anonymous class
  ### Should I then be saying I'm done mutating it with something like this?
  ### can make_immutable even be run on an object instance and not a package?
  $self->meta->make_immutable;
}

Даже еслиПриведенный выше код работает для отдельного пакета, что происходит, когда объект восстанавливает себя с ролью 'Foo', в результате чего получается анонимный класс, затем второй объект благословляет себя 'Foo' (становясь тем же классом anon), затем 'Bar'роль?Будет ли он работать правильно, когда второй объект благословит себя в неизменяемом первом анонимном классе, а затем попытается применить эту роль к теперь неизменяемому анонимному классу, чтобы создать новый анонимный класс?

Из чтения документов на Moose :: Meta :: Class , похоже, неизменным может быть только класс, а не экземпляры объектов.Если да, то должен ли я просто игнорировать make_immutable, поскольку я мутирую в своих классах?

1 Ответ

7 голосов
/ 28 марта 2011

Вы должны делать make_immutable как обычно в нижней части вашего класса, и вообще не беспокоиться об этом в своем BUILD.

Когда вы применяете роль к экземпляру во время выполнения, это нене изменять класс экземпляра для применения роли (это было бы грязно и ужасно и влияло бы на все другие экземпляры этого класса);он создает новый анонимный класс, который наследуется от вашего класса, а также выполняет запрошенные роли, а затем вклинивает экземпляр в этот класс.Поскольку исходный класс не изменяется, нет никаких проблем с тем, является ли он открытым / изменяемым или нет.

Вы на самом деле можете сделать $self->meta->make_immutable после применения роли - он будет иммобилизован вновьсозданный анонимный класс - и для полноты вы, вероятно, должны.Но это принесет лишь небольшое преимущество, поскольку большая часть того, что делает make_immutable, состоит в том, чтобы сделать конструктор быстрее, а конструктор нового класса все равно не запускается.

Если вы хотите увидеть подробности того, какролевое приложение к экземплярам работает, вам следует взглянуть на источник Moose :: Meta :: Role :: Application :: ToInstance .

...