Почему строитель Moose принимает строковое значение? - PullRequest
7 голосов
/ 18 февраля 2009

Moose :: Manual :: Attributes состояния:

В качестве альтернативы использованию ссылки на подпрограмму [по умолчанию] вы можете вместо этого предоставить метод построителя для вашего атрибута: ... Это имеет несколько преимуществ. Во-первых, он перемещает фрагмент кода в свой собственный именованный метод, что улучшает удобочитаемость и организацию кода.

Итак, ваш атрибут может определить значение по умолчанию таким образом:

has attr => (
  is => 'ro',
  builder => 'subroutine'
);
sub subroutine {
  # figure out and return default value
}

Я не понимаю, почему это должно быть отдельно от значения по умолчанию. Не могли бы вы просто передать ссылку на именованную подпрограмму?

has attr => (
  is => 'ro',
  default => \&subroutine
);

И разве это не будет лучшей практикой программирования, поскольку вы гарантированно не будете случайно ссылаться на подпрограмму, которая не существует? Вы будете ссылаться на метод с логической ссылкой вместо символической ссылки.

Ответы [ 3 ]

14 голосов
/ 18 февраля 2009

Когда вызывается строитель, это происходит:

$object->$builder

Если builder - строка (скажем, build_attr), тогда пользователи могут написать свой собственный метод build_attr в подклассе, и он будет вызван. Это делает значение по умолчанию расширяемым с помощью простого механизма именованных методов.

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

10 голосов
/ 18 февраля 2009

Это не «символическая» ссылка. Строитель - это метод name . Это означает, что он наследуем и составлен из роли. Если вы передаете ссылку на подпрограмму, эта ссылка должна существовать в том же пакете (или быть полностью квалифицированной).

Я почти уверен, что объясню это в руководстве. Неясно?

7 голосов
/ 18 февраля 2009

подклассов.

Builder указывает имя метода для вызова, поэтому

package Something;
use Moose;

extends 'YourClass';

sub subroutine { <some other default> }

будет вызывать подпрограмму Something :: для компоновщика 'подпрограммы', тогда как если вы используете стиль subref, тогда будет вызываться подпрограмма YourClass ::, потому что вы сделали прямую ссылку на подпрограмму вместо того, чтобы позволить ей пройти метод отправки.

...