Sub-classing LCFG components

One topic that often comes up in discussions about how to make things easier for LCFG component authors is the idea of sub-classing.

Although I had never tried it I had always assumed this was possible. Recently whilst looking through the LCFG::Component code I noticed that the list of methods are looked up in the symbol table for the module:

    my $mtable = {};
    for my $method ( ( keys %LCFG::Component:: ),
        ( eval 'keys %' . ref($self) . q{::} ) )
    {
        if ( $method =~ m/^method_(.*)/i ) {
            $mtable->{ lc $1 } = $method;
        }
    }
    $self->{_METHOD} = lc $_METHOD;
    my $_FUNCTION = $mtable->{ $self->{_METHOD} };

So, this will work if your method comes from LCFG::Component or LCFG::Component::Foo but it wouldn’t work if you have a sub-class of Foo. You would potentially miss out on methods which are only in Foo (or have to copy/paste them into your sub-class).

Not only does this make sub-classing tricky it also involves a horrid string eval. There had to be a better way. Thankfully I was already aware of the Class::Inspector module which can do the necessary. This module is widely used by projects such as DBIx::Class and Catalyst so is likely to be reliable. It has a handy methods method which does what we need:

    my $_FUNCTION;
    my $public_methods = Class::Inspector->methods( ref($self), 'public' );
    for my $method (@{$public_methods}) {
        if ( $method =~ m/^Method_(\Q$_METHOD\E)$/i ) {
            $_FUNCTION = $method;
            $_METHOD = $1;
            last;
        }
    }

Much nicer code and a tad more efficient. Now the LCFG component Perl modules are properly sub-classable.

Comments are closed.