Not Enough Abuse (bummer)

Ovid on 2007-04-19T14:07:34

Try as I might, I can't get two instances of a class to have different inheritance trees at the same time. @ISA is a package variable, so changing it affects all instances. Hmm, can @ISA be tied? You'd have to invalidate the cache every time you did anything and this would be bad, wicked, evil, wrong, etc., but I'm still curious to know if it can be done.

Or ... maybe I could bless every instance into an anonymous subclass and ... oh wait, I can't tie symbol tables. Damn. Maybe I could use anonymous subclasses, do some introspection and pulled out method names and provided wrapper which switched @INC that way...

ACME::DiddleMyInc needs to be written!


Talking to Myself

Ovid on 2007-04-19T15:04:34

The closest I've come up with so far is this:

#!/usr/bin/perl -l

use strict;
use warnings;

{

    package KillMeNow;
    sub whee { return 'whee!' }
    sub new { bless {}, shift }
}

{

    package DontKillMe;
    sub whee { return 'asdfasdf' }
}

{

    package KillMeLater;
    @KillMeLater::ISA = 'KillMeNow';
    use overload '%{}' => sub {
        @KillMeLater::ISA =
          rand 1 > .5
          ? 'KillMeNow'
          : 'DontKillMe';
        return shift;
      },
      fallback => 1;

    sub new { bless {} => shift }
    sub whee {
        my $self = shift;
        no warnings 'void';
        %$self;
        $self->SUPER::whee;
    }
}

for ( 1 .. 20 ) {
    print KillMeLater->new->whee;
}

It works, but it's not what I wanted. I could possibly automate that, but this is harder than it seems.

Full power...now sir.

melo on 2007-04-19T15:08:14

We need support for coderefs @ISA, like in @INC :)

Re:Full power...now sir.

Ovid on 2007-04-19T15:11:02

Yeah, we were talking about that here at work. It would have solved an annoying little problem here (well, more of a hack to get around some buggy CPAN code).

well...

rjbs on 2007-04-19T15:13:43

What effect do you really need? You could use an AUTOLOAD which can build a dispatch path and query it on a per-object basis. Or you could generate a new package for each object with the proper path to which calls are delegated by the apparent class. Fixing isa() would not be too difficult, I think.

This would not affect @ISA, though, if you need that to work.

why?

perrin on 2007-04-19T15:34:41

Why would you want to do that?

Re:why?

Ovid on 2007-04-19T15:37:20

Note the Acme:: prefix on the suggested namespace.

use Moose

groditi on 2007-04-19T17:17:31

I use instance-based modifications to classes by using Moose and MooseX::Object::Pluggable which I wrote. The basic idea is to use Class::MOP to generate an anonymous class that has feature XYZ you want that inherits from your original class. sounds like you already thought of it, but it works quite nicely and easily with the introspection

Re:use Moose

Aristotle on 2007-04-20T00:18:04

That would be my angle of attack also.

What EXACTLY are you trying to do...

Alias on 2007-04-20T04:05:52

... and why do you think that necesarily needs to involve changing @ISA?

@ISA is just an array store used by the default implementation of the ->isa method to determine is something isa something else, and by the method resolved.

If you want to fake being an object, them perhaps just overload ->isa?

Or then there's a Decorator object...

I'm not sure why making objects do weird things needs to involve @ISA.

Re:What EXACTLY are you trying to do...

Ovid on 2007-04-20T08:00:45

It's not that I want to have different instances with different inheritance trees. I just want to know if it can be done. It's a matter of curiosity, that's all.