【问题标题】:What's the best way to discover all subroutines a Perl module has?发现 Perl 模块的所有子例程的最佳方法是什么?
【发布时间】:2010-10-11 01:45:46
【问题描述】:

以编程方式发现 perl 模块的所有子例程的最佳方法是什么?这可能是一个模块、一个类(没有@EXPORT)或任何介于两者之间的东西。

编辑:下面的所有方法看起来都可以工作。我可能会在生产中使用 Class::Sniff 或 Class::Inspector。然而,Leon 的回答被标记为“接受”,因为它回答了所提出的问题,即使必须使用no strict 'refs'。 :-) Class::Sniff 可能是一个不错的选择。看来是经过深思熟虑的。

【问题讨论】:

    标签: perl reflection perl-module subroutine


    【解决方案1】:
    sub list_module {
        my $module = shift;
        no strict 'refs';
        return grep { defined &{"$module\::$_"} } keys %{"$module\::"}
    }
    

    ETA:如果你想过滤掉导入的子程序,你可以这样做

    use B qw/svref_2object/;
    
    sub in_package {
        my ($coderef, $package) = @_;
        my $cv = svref_2object($coderef);
        return if not $cv->isa('B::CV') or $cv->GV->isa('B::SPECIAL');
        return $cv->GV->STASH->NAME eq $package;
    }
    
    sub list_module {
        my $module = shift;
        no strict 'refs';
        return grep { defined &{"$module\::$_"} and in_package(\&{*$_}, $module) } keys %{"$module\::"}
    }
    

    【讨论】:

    • 这也会列出该模块从其他模块导入的子程序。
    • 再想一想,这也可能很重要,具体取决于应用程序。
    • 没错,但我认为没有简单的方法可以解决这个问题。 namespace::clean 是此类问题的答案 ;-)
    • 您希望存在而不是定义为拾取自动加载的潜艇。
    • 第二个 \&.. 在第二个 list_module 中应该与第一个相同。此外,in_package 不会在 5.10 上为我过滤导入的常量...将研究
    【解决方案2】:

    Class::Inspector:

    Class::Inspector 允许您获取有关已加载类的信息。大多数或所有这些信息都可以通过其他方式找到,但它们并不总是非常友好,并且通常涉及相对较高水平的 Perl 魔法,或者看起来很奇怪和不寻常的代码。 Class::Inspector 试图为这些信息提供一个更简单、更友好的界面...

    【讨论】:

    • 很有意思,我去看看。
    • 对我来说,这个答案比 Leon 的要好,因为我需要所有对象方法(继承链中的所有内容)。
    • 在 perl 调试器中使用 Class::Inspector 非常有用,谢谢。
    【解决方案3】:

    看看这个: Class::Sniff

    该界面目前相当临时,并且可能会发生变化。创建新实例后,调用报告方法是您的最佳选择。然后,您可以直观地检查它以寻找潜在的问题:

    my $sniff = Class::Sniff->new({class => 'Some::Class'});
    print $sniff->report;
    

    该模块试图帮助程序员在面向对象的代码中发现“代码异味”。如果它报告了什么,这并不意味着你的代码是错误的。这只是意味着您可能想更仔细地查看您的代码,看看您是否有任何问题。

    目前,我们假设 Perl 的默认最左、深度优先搜索顺序。我们将来可能会改变它(并且有一个解决方法是使用 paths 方法。稍后会详细介绍)...

    【讨论】:

    • 看起来很有趣,但相当新。我会犹豫在生产环境中使用它。
    • 在生产环境中,您可能有什么理由获得方法列表?
    • 我有兴趣制作一个类似于 Test::Class 的工具的原型。用其他未经测试的代码开发原型可能会让人头疼。 :)
    • 好点。我只是希望你不要在生产服务器上进行测试。
    • 这是新事物,但 Ovid 对这个问题进行了深入的思考。不是随便写的。在此处查看与 Class::Sniff 相关的各种期刊帖子:use.perl.org/journal.pl?op=list&uid=2709
    猜你喜欢
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    相关资源
    最近更新 更多