如何查找我在 Perl 上拥有的对象类型?

问题描述 投票:0回答:4

如何找到我正在 Perl 中处理的对象类型? 我尝试使用 perl -d 进入调试器,但我不知道接下来该怎么做。 同样,我想要一种方法来轻松查看每个对象可以使用哪些方法,如何才能做到这一点?

perl debugging
4个回答
31
投票

判断您拥有的对象类型的标准方法是

ref
Scalar::Util
::blessed
。如果您知道该对象受到祝福,那么它们会返回相同的信息。

my $class1 = blessed( $obj );
my $class2 = ref $obj;

但是

ref
也会为未受祝福的哈希值返回“HASH”,而
blessed
拒绝玩该游戏。

至于方法列表,对于 Perl 对象受祝福的指针样式,您自己编写一个方法很容易。下面的代码对我来说效果很好。它返回映射到定义它们的包的函数名称(那些采用给定名称的“代码槽”的函数)。

sub class_methods { 
    use Class::ISA;
    my $obj = shift;
    return unless ref( $obj );
    my %meth_names;
    foreach my $anc ( Class::ISA::self_and_super_path( ref $obj ), 'UNIVERSAL' ) {
        my $stash = \%{"$anc\::"};
        my @funcs 
            = grep { m/^[_\p{Alpha}]/                # begins with _ or alpha
                   && !exists $meth_names{$_}        # no clobbering
                   &&  defined *{$stash->{$_}}{CODE} # has a filled CODE slot
                   } keys %$stash
            ;
        # assign to the "hash slice", keyed by all the entries in @funcs
        # the value of $anc repeated as many times as elements in @funcs.
        @meth_names{@funcs} = ( $anc ) x @funcs;
    }
    return %meth_names;
}
  • 这也适用于相当复杂的对象,但是如果所属包包含大量生成的代码,那么了解生成器将代码指针插入哪个包就没有多大帮助了。这将意味着更多的查找什么包生成了代码。

  • 在这种情况下,您可能会从运行代码中获取代码,包括

    Data::Dumper
    并将
    $Data::Dumper::Deparse
    设置为1,如下所示:(
    local $Data::Dumper::Deparse = 1;
    )然后转储代码指针,例如所以:
    say Dumper( $code_ref );

  • WON'T适用于尚未由任何

    AUTOLOAD
    方法创建的有效方法。如果您在列表中看到这些内容,则该对象可能会执行更多操作,但您不知道它做了什么。

  • 包含“基类”

    UNIVERSAL
    ,因为该类包含对象可用的行为。

祝你好运。


8
投票

来自 Scalar::Util

blessed 函数将告诉您任何受祝福的引用(对象)的包名称。

要了解可用的方法,请查阅该包的文档。或者,您可以使用类似 Class::MOP::Class 来实例化元类并获取有关它包含的方法的内省信息。


3
投票

为了完整起见,这里有一个关于调试器的简短介绍。

perl -d your_program

在 bugger 下启动它。您将在第一个可执行行获得控制(use 语句等已在此时执行)。

's' 将进入下一行。输入“s”后,只需按回车键即可重复输入。 's' 将逐步进入函数/子例程/方法。要么继续单步执行直到返回,要么输入“r”命令来执行函数的其余部分并在调用后立即返回。

如果您想“跳过”子例程 - 即执行它们并返回,而不必介入并返回,请使用“n”。第一个“n”之后的回车也会继续为您做“n”。

如果您知道要停止的行,请使用“b”命令 - b 行号 - 设置断点,然后使用“c”继续,直到到达它。请注意,每次您“c”并返回到断点时,您都会再次停止。使用“B linenumber”关闭断点。

所以我们假设你已经得到了这样的结果:

my $obj = complex_function_returning_unknown_thing;

调试器刚刚向您显示了这一行,其中表示“我还没有执行此操作,但这是我下一步要做的。”输入“n”执行子例程,然后使用“x”命令查看对象:“x $obj”。如果它很大,您可以说“|x $obj”,它通过寻呼机运行输出。要查看对象有哪些方法,请使用“m $obj”。

调试器还有很多功能,但您确实可以将它用于此类事情 - 您只需查看从某些代码中获取的对象的类型,并找出您获取的对象具有哪些方法。

“x”该对象可能更有用,然后查看该对象被祝福的类的源代码,以找出您“应该”做什么,而不是“可以”做什么。无论如何,“x”命令几乎是“print ref($obj)”与 Data::Dumper 的交叉。 您正在寻找 Perl 中的反射。我刚刚用谷歌搜索了不带引号的“Perl Reflection”,结果出现了:


-1
投票
perl.beginners:回复:perl 中的反射

编辑:

还有这个: 回复:perl 中的反射 - Todd W - org.perl.beginners - MarkMail 编辑:

还有这个: 反思性编程 - 维基百科

© www.soinside.com 2019 - 2024. All rights reserved.