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


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

Thanks, but I'm not sure I follow. The documentation doesn't mention using Moose::Util::TypeConstraints. What, exactly, does the code in the documentation do?</code>

$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^3: Delegating to a role in Moose
by Arunbear (Prior) on Jan 12, 2018 at 18:22 UTC
    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?

      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

        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.