Home > Uncategorized > Make Children, not War

Make Children, not War

While teaching META6::bin how to read a config file, I was thinking about handling URIs by creating individual types per schema. That would require a factory what is not to my liking. I don’t use a dymanic language just to implement all that nice redundancy sugested in Design Patterns.

But then I reaslised that I use a dynamic language what means I can have a factory without implementing it. As long as I keep all subclasses in the same compunit then the parent class, that parent can use package introspection to collect all children and implement the factory method in its .new method.

class URL is export {
    my $.subclasses;

    our $.schema;
    has Str $.host;
    has $.raw;

    multi method new(Str $url) {
        $.subclasses //= UNIT::.values.grep({$_ ~~ URL && .schema});

        for $.subclasses.flat {
            return $_.new(:raw($url)) if $url.starts-with(.schema ~ '://');
        }
    }

    method host {
        $!host //= $.raw.substr($.raw.index('://') + 3).substr(0, $.raw.index('/') + 1);
    }
}

class HTTP is URL is export {
    our $.schema = 'http';
}

class HTTPS is URL is export {
    our $.schema = 'https';
}

sub url(|c){
    URL.new(|c)
}

say url('https://foo.com/bar.p6').host;

UNIT::.values returns a list of type objects that we can check against in the constructor. The class variable $.schema is used to pick the right child to return.

One could take that a step further and add a trait to register a child and a thunk with the base class to move the decision making what object to return to the children. That way a child could be moved to a different compunit as well.

Advertisements
Categories: Uncategorized
  1. No comments yet.
  1. April 10, 2017 at 22:58

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: