http://www.perlmonks.org?node_id=1015219


in reply to Can't call method "MoveBook" on an undefined value

You should use a default or builder for the attributes. Defaults work like this:

package LibraryTest; use Moose; use Book; has unread_books => ( is =>'rw', isa => 'ArrayRef[Book]', default => sub { [] }, ); has read_books => ( is =>'rw', isa => 'ArrayRef[Book]', default => sub { [] }, );

Builders work like this:

package LibraryTest; use Moose; use Book; has unread_books => ( is =>'rw', isa => 'ArrayRef[Book]', builder => '_build_unread_books', ); has read_books => ( is =>'rw', isa => 'ArrayRef[Book]', builder => '_build_read_books', ); sub _build_unread_books { return []; } sub _build_read_books { return []; }

Defaults are very convenient to define, but builders are arguably a better way to do things: the builder is a regular method, so subclasses can easily override it, which is handy.

Builders are a very handy thing when you get used to them - especially when you use them in conjunction with Moose's lazy attribute initialisation feature.

package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name