Search code examples
perltypesmoo

How do I check if an object is valid when pushed to an ArrayOf[] member in my perl Moo class?


I have created a Moo class containing an array of objects which is checked against a type using Types::Standard and I want to verify that I'm placing the right objects into that array without hard-coding too much. Here is an example of what I have right now:

package MyClass;
use Moo;
use Types::Standard qw( ArrayRef InstanceOf );

# Initially empty array of objects
has connected => (
    is => 'ro',
    isa => ArrayRef[InstanceOf['MyClass']],
    default => sub { [] }
);

# Add an object to our internal list
sub connect {
    my ( $self, $other ) = @_;
    # TODO: Check if "$other" is actually an InstanceOf['MyClass']
    # without doing "$self->connected( $self->connected )"
    push @{$self->connected}, $other;
}

In connect() I add objects to my internal array but if I understand correctly, the object is never checked against InstanceOf['MyClass'] since I don't actually set the array reference again.

What would be a good way to perform this validation on each new object? I briefly thought about doing $self->connected( $self->connected ) after having pushed a new item but that would have to verify every object.

Ideally I would not even want to know exactly what's in the ArrayRef, only that it is something that has to be checked. I took a look at _type_parameter_ in the documentation for Type::Tiny but I couldn't quite figure out how to use it in my code.


Solution

  • An answer for an old question because I've been unable to log in to StackExchange for quite a while...

    package MyClass;
    use Moo;
    use Types::Standard qw( ArrayRef InstanceOf );
    use Sub::HandlesVia;
    
    has connected => (
        is => 'ro',
        isa => ArrayRef[InstanceOf['MyClass']],
        default => sub { [] },
        handles_via => 'Array',
        handles => {
          'connect' => 'push',
        }
    );
    

    Sub::HandlesVia will automatically take care of the type check for you.