24

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

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

4

3 回答 3

23
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\::"}
}
于 2009-03-03T17:29:56.430 回答
12

类::检查员

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

于 2009-03-03T19:27:51.483 回答
9

看看这个: Class::Sniff

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

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

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

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

于 2009-03-03T18:08:17.213 回答