in reply to Re^2: Delegating to a role in Moose
in thread Delegating to a role in Moose

Moose::Util::TypeConstraints isn't really important here and I should have edited it out of the snippet. The important thing to understand is
package Foo::Bar; use Moose::Role; requires 'foo'; requires 'bar';
i.e. required methods. This is how a role indicates that a class consuming it should have some extra behaviour that the role depends on. Taking this to an extreme you can even have a role that only has required method specifiers - this gives you something similar to the interface construct found in Java/C#/PHP.

And this latter type of role is what is intended to be used when you specify a role to the 'handles' clause.

Does that make sense?

Replies are listed 'Best First'.
Re^4: Delegating to a role in Moose
by nysus (Vicar) on Jan 12, 2018 at 21:57 UTC

    In the documentation, it's made to look like you can extend or override methods provided by URI but from what I can tell it does nothing of the sort. Take this, for example, which emulates what is in the documentation:

    { package MyURIRole 0.000001; use Moose::Role; requires 'host'; requires 'path'; sub print_hi { my $s = shift; print "hi\n"; } } { package MyURI 0.000001; use Carp; use Moose; use URI; has 'uri' => ( is => 'ro', isa => 'URI', handles => 'MyURIRole', ); } #! /usr/bin/env perl use MyURI; use strict; use warnings; my $uri = MyURI->new( uri => URI->new('')) +; print $uri->host; print "\n"; print $uri->path; print "\n"; $uri->print_hi;

    From the documentation's explanation, I would expect the $uri->print_hi to print out "hi". Instead, I get an error:

    Can't locate object method "print_hi" via package "URI::http" at inline delegation in MyURI for uri->print_hi (attribute declared in at line 7) line 18.

    So I'm not sure why the documentation is suggesting that using a role name with handles is a good way to delegate when using another package like URI. What is to be gained from it? Am I missing something?

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

      Well this is what the docs say:
      With the role option, you specify the name of a role or a role type whose "interface" then becomes the list of methods to handle. The "interface" can be defined as; the methods of the role and any required methods of the role. It should be noted that this does not include any method modifiers or generated attribute methods (which is consistent with role composition).
      So in your example
      has 'uri' => ( is => 'ro', isa => 'URI', handles => 'MyURIRole', );
      means that the methods of MyURIRole i.e. 'host', 'path' and 'print_hi' will be delegated to the 'uri' attribute, which in this case is an object of class "URI::http" and that class doesn't provide a "print_hi" method.

      To reiterate, MyURIRole is only being used by 'handles' in an informational way (i.e. to determine the names of delegated methods), it does not use the role to provide the method implementations.

        Alright, thanks. I guess my only question left, then, is why would you use something like handles => 'MyURIRole' over handles => qr/.*/? The latter seems a lot more useful and it does allow me to extend the URI class with my own methods very easily and which seems enormously useful. However, I found it very odd that after doing a lot of searching on this, there is only one tutorial I could find that even mentions the handles => qr/.*/ method for delegating. The omission from the documentation of this method for delegating makes me wonder if it's advisable to do (and hence why I looked into using a more "official" way by using a role name instead).

        Overall, it just seems the documentation on delegation is lacking a bit, especially for someone like me who doesn't have a lot of experience with OO patterns and is more or less just following recipes without understanding the chemistry behind the cooking. Maybe I should reach out to the module authors? What do you think?

        $PM = "Perl Monk's";
        $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
        $nysus = $PM . ' ' . $MCF;
        Click here if you love Perl Monks