【问题标题】:Detecting Overridden Methods in Perl在 Perl 中检测被覆盖的方法
【发布时间】:2010-10-12 00:59:36
【问题描述】:

上周我被两次意外地覆盖了子类中的方法。虽然我不喜欢继承,但我们(ab)在我们的应用程序中使用它。我想做的是提供一些声明性语法来说明方法正在覆盖父方法。像这样的:

use Attribute::Override;

use parent 'Some::Class';

sub foo : override { ... } # fails if it doesn't override
sub bar { ... }            # fails if it does override

这里有几个问题。首先,如果方法加载以某种方式延迟(例如,通过 AUTOLOAD 加载的方法或稍后安装在符号表中的方法),则不会检测到这些方法。

遍历继承树也可能会变得同样昂贵。我使用Class::Sniff 执行此操作,但它并不适合运行代码。我可以遍历继承树并简单地匹配相应符号表中已定义 CODE 槽的位置,这样会更快,但如果方法缓存无效,如果我要缓存这些结果,就会中断。

所以我有两个问题:这是一种合理的方法吗?是否有一个钩子可以让我检查方法缓存是否已更改? (在“perldoc perlobj”中搜索“缓存”)。

当然,这不应该破坏生产代码,我正在考虑仅在 TEST_HARNESS 环境变量处于活动状态时让它失败或发出警告(并且如果生产代码要使用显式环境变量来强制它处于非活动状态)出于某种原因设置 TEST_HARNESS 环境变量)。

【问题讨论】:

    标签: perl oop methods overriding


    【解决方案1】:

    一种强制执行的方法:

    package Base;
    ...
    sub new {
        my $class = shift;
        ...
        check_overrides( $class );
        ...
    }
    
    sub check_overrides {
        my $class = shift;
        for my $method ( @unoverridable ) {
            die "horribly" if __PACKAGE__->can( $method ) != $class->can( $method );
        }
    }
    

    check_overrides 的记忆可能会有所帮助。

    如果在某些情况下您需要豁免,请使用备用方法名称并 让基类调用:

    package Base;
    ...
    my @unoverridable = 'DESTROY';
    sub destroy {}
    sub DESTROY {
        my $self = shift;
        # do essential stuff
        ...
        $self->destroy();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2011-11-06
      • 2011-12-13
      • 1970-01-01
      • 1970-01-01
      • 2013-07-13
      • 2013-07-14
      相关资源
      最近更新 更多