Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><code>new</code> builds the builder. You want some other method to actually return the built object.</p> <p>Here's an example:</p> <pre><code> class RepositoryBuilder { has 'allow_network_repositories' =&gt; ( is =&gt; 'ro', isa =&gt; 'Bool', required =&gt; 1, ); method build_repository(Uri $url) { confess 'network access is not allowed' if $url-&gt;is_network_url &amp;&amp; !$self-&gt;allow_network_repositories; my $class = $self-&gt;determine_class_for($url); # Repository::Whatever return $class-&gt;new( url =&gt; $url ); } } role Repository { &lt;whatever } class Repository::File with Repository {} class Repository::HTTP with Repository {} </code></pre> <p>Here, the builder and the built object are distinct. The builder is a real object, complete with parameters, that can be customized to build objects as the situation demands. Then, the "built" objects are merely return values of a method. This allows you to build other builders depending on the situation. (A problem with builder functions is that they are very inflexible -- it's hard to teach them a new special case. This problem still exists with a builder object, but at least your application can create a subclass, instantiate it, and pass this object to anything that needs to create objects. But dependency injection is a better approach in this case.)</p> <p>Also, there is no need for the repositories you build to inherit from anything, they just need a tag indicating that they are repositories. And that's what our <code>Repository</code> role does. (You will want to add the API code here, and any methods that should be reused. But be careful about forcing reuse -- are you sure everything tagged with the Repository role will want that code? If not, just put the code in another role and apply that one to the classes that require that functionality.)</p> <p>Here's how we use the builder we created. If, say, you don't want to touch the network:</p> <pre><code>my $b = RepositoryBuilder-&gt;new( allow_network_repositories =&gt; 0 ); $b-&gt;build_repository( 'http://google.com/' ); # error $b-&gt;build_repository( 'file:///home/whatever' ); # returns a Repository::Foo </code></pre> <p>But if you do:</p> <pre><code>my $b = RepositoryBuilder-&gt;new( allow_network_repositories =&gt; 1 ); $b-&gt;build_repository( 'http://google.com/' ); # Repository::HTTP </code></pre> <p>Now that you have a builder that builds the objects the way you like, you just need to use these objects in other code. So the last piece in the puzzle is referring to "any" type of Repository object in other code. That's simple, you use <code>does</code> instead of <code>isa</code>:</p> <pre><code>class SomethingThatHasARepository { has 'repository' =&gt; ( is =&gt; 'ro', does =&gt; 'Repository', required =&gt; 1, ); } </code></pre> <p>And you're done.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload