http://qs321.pair.com?node_id=1207171


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

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('http://www.perl.com/the_path')) +; 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 MyURI.pm 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

Replies are listed 'Best First'.
Re^5: Delegating to a role in Moose
by Arunbear (Prior) on Jan 13, 2018 at 18:14 UTC
    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

        Re: handles => 'MyURIRole' vs handles => qr/.*/, the former is more work to set up, but I think it should be preferred because it's more self documenting - you've documented in code exactly what methods you're delegating.

        I agree that the documentation on delegation is lacking, but that's a symptom of a larger problem. E.g. the official docs on Perl OOP, perlobj and perlootut don't mention delegation at all.