incubusaurus has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I've been trying to create a simple subclass of Gearman::XS::Client, but seem unable to do so. I can instantiate the subclass, but the object is not of the correct class:
use Test::More; use strict; use warnings; { package My::Gearman::Client; use parent 'Gearman::XS::Client'; sub foo {} } my $gm = My::Gearman::Client->new; isa_ok($gm, 'Gearman::XS::Client'); # Pass isa_ok($gm, 'My::Gearman::Client'); # Fail can_ok($gm, 'foo'); # Fail
The code works as expected if I substitute Gearman::XS::Client with another module, such as JSON::XS. I've tried use parent, use base, manually modifying @ISA, and using extends from Mouse. I'm assuming that the problem is caused by Gearman::XS::Client, buy why?

Replies are listed 'Best First'.
Re: Cannot subclass Gearman::XS::Client
by MidLifeXis (Monsignor) on Jul 24, 2014 at 19:47 UTC

    I would guess that this line in Client.xs has something to do with it. It is explicitly setting the class to the package name.

    As much as I dislike reblessing, perhaps implementing a new() method that calls SUPER::new with the passed parameters and then reblesses it into your class would work.

    You could also use delegation, and store the G::XS::C object on your object and call it when needed. One benefit that this could give is that you can change out the underlying implementation and leave your API the same.

    --MidLifeXis

      Thanks. It looks as though you are right. Reblessing the object works, but I'll experiment with delegation too.
Re: Cannot subclass Gearman::XS::Client
by runrig (Abbot) on Jul 24, 2014 at 19:51 UTC
    Your code requires Gearman::XS::Client to bless the object into the class 'My::Gearman::Client'. Gearman::XS::Client does not necessarily do this. Although the common way to write a constructor is something along the lines of:
    sub new { my $class = shift; bless {}, $class; }
    Not all modules will do it this way, and will bless into some constant class name. That appears to be what is happening. You can try filing a bug report (hopefully with a patch) that the module cannot be sub-classed, or you can make your library a delegator instead of a parent class.
      I've not worked with XS code before, but this looks like an interesting little challenge for me. Time permitting, I'll have a stab at creating a patch.