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

I would like to allow others to extend my code on the fly by allowing them to write methods and then install them in a simple fashion. My desire to have this happen dynamically is driven by the idea that I could use this as a cheating way to have the object switch into different modes of operation just by overriding current methods.

At the moment all I can think of is a hash dispatch table, but this seems to rule out calls like $object->custom_method unless maybe autoload (which I am kind of frightened of) can be persuaded to do it.

____________________
Jeremy
I didn't believe in evil until I dated it.

Replies are listed 'Best First'.
Re: Dynamic object extensions
by dws (Chancellor) on Nov 03, 2001 at 09:01 UTC
    At the moment all I can think of is a hash dispatch table, but this seems to rule out calls like $object->custom_method unless maybe autoload (which I am kind of frightened of) can be persuaded to do it.

    Face your fears. Embrace AUTOLOAD.

    Here is one approach:

    package Frob; sub new { my $pkg = shift; bless {}, $pkg } sub customize { my ($self, $method, $code) = @_; $self->{_custom}->{$method} = $code; } sub AUTOLOAD { my $self = shift; my $method = $AUTOLOAD; $method =~ s/.*:://; if ( exists $self->{_custom}->{$method} ) { $self->{_custom}->{$method}->(@_) } else { die "no code for '$method'"; } } package main; $|++; # so as not to suffer from buffering my $frob = new Frob(); $frob->customize('foo', sub { print "foo @_!\n" }); $frob->foo(42); # should work $frob->bar(42); # should fail
Re: Dynamic object extensions
by ton (Friar) on Nov 03, 2001 at 09:12 UTC
    Have you considered evaling the subroutines you want to overwrite? For example, here is a class that can have its foo method overwritten:
    package MyPack; use strict; sub new($$) { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { }; bless($self, $class); return $self; } sub foo($) { my $self = shift; print "foo is unmodified.\n"; } sub changeFoo($) { my $line; my $code; while ($line = <DATA>) { $code .= $line; } eval $code; } 1; __DATA__ sub foo($) { my $self = shift; print "foo has been modified.\n"; }
    Here's some code to test it:
    use MyPack; use strict; my $obj = MyPack->new(); $obj->foo(); $obj->changeFoo(); $obj->foo();
    The output is
    foo is unmodified. foo has been modified.
    Of course, there's no reason for the changing code to be in DATA; it can just as easily be in a seperate file.

    -ton
    -----
    Be bloody, bold, and resolute; laugh to scorn
    The power of man...

Re (tilly) 1: Dynamic object extensions
by tilly (Archbishop) on Nov 03, 2001 at 09:22 UTC
    An alternate solution is BikeNomad's Class::Prototyped which offers private methods, and goes out of its way to avoid the speed hit of AUTOLOAD.
Re: Dynamic object extensions
by data64 (Chaplain) on Nov 04, 2001 at 09:59 UTC

    Someone please correct me if I am wrong. But doesn't inheritance do just that.

    Specifically, you create you own object oriented module and if someone wants to change the behaviour, they can inherit and override some of the methods.

      That only happens when the program runs. All the above solutions are excellent ways to do this while the program is running

      ____________________
      Jeremy
      I didn't believe in evil until I dated it.