How can I redefine Perl class methods?

前端 未结 5 1798
日久生厌
日久生厌 2020-12-30 08:27

The question \"How can I monkey-patch an instance method in Perl?\" got me thinking. Can I dynamically redefine Perl methods? Say I have a class like this one:



        
相关标签:
5条回答
  • 2020-12-30 08:41

    You can overwrite methods like get_val from another package like this:

    *{MyClass::get_val} = sub { return $some_cached_value };
    

    If you have a list of method names, you could do something like this:

    my @methods = qw/ foo bar get_val /;
    foreach my $meth ( @methods ) {
        my $method_name = 'MyClass::' . $meth;
        no strict 'refs';
        *{$method_name} = sub { return $some_cached_value };
    }
    

    Is that what you imagine?

    0 讨论(0)
  • 2020-12-30 08:50

    Not useful in your case but had your class been written in Moose then you can dynamically override methods using its Class::MOP underpinnings....

    {
        package MyClass;
        use Moose;
    
        has 'val' => ( is => 'rw' );
    
        sub get_val {
            my $self = shift;
            return $self->val + 10;
        }
    
    }
    
    my $A = MyClass->new( val => 100 );
    say 'A: before: ', $A->get_val;
    
    $A->meta->remove_method( 'get_val' );
    $A->meta->add_method( 'get_val', sub { $_[0]->val } );
    
    say 'A: after: ', $A->get_val;
    
    my $B = MyClass->new( val => 100 );
    say 'B: after: ', $B->get_val;
    
    # gives u...
    # => A: before: 110
    # => A: after: 100
    # => B: after: 100
    
    0 讨论(0)
  • 2020-12-30 08:53

    I've never tried it with methods, but Memoize may be what you're looking for. But be sure to read the caveats.

    0 讨论(0)
  • 2020-12-30 08:54

    How do I modify to just do this?:

    cache_fn(\&myfn);

    Well based on your current example you could do something like this....

    sub cache_fn2 {
        my $fn_name = shift;
        no strict 'refs';
        no warnings 'redefine';
    
        my $cache_value = &{ $fn_name };
        *{ $fn_name } = sub { $cache_value };
    }
    
    cache_fn2( 'myfn' );
    

    However looking at this example I can't help thinking that you could use Memoize instead?

    0 讨论(0)
  • 2020-12-30 08:56

    I write about several different things you might want to do in the "Dynamic Subroutines" chapter of Mastering Perl. Depending on what you are doing, you might want to wrap the subroutine, or redefine it, or subclass, or all sorts of other things.

    Perl's a dynamic language, so there is a lot of black magic that you can do. Using it wisely is the trick.

    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题