有没有办法知道Perl中未知类的实例的方法
我有一个Perl程序,它使用我从另一个来源获得的包。该方法的一个函数返回一个未知类的对象,我有没有办法在不查看对象的类实现的情况下获取对象的所有可能方法?不太可能 TL;医生:有没有办法知道Perl中未知类的实例的方法,perl,object,Perl,Object,我有一个Perl程序,它使用我从另一个来源获得的包。该方法的一个函数返回一个未知类的对象,我有没有办法在不查看对象的类实现的情况下获取对象的所有可能方法?不太可能 TL;医生: 您可以找到显式声明或放置在对象类命名空间中的子例程的名称 您无法区分这些子例程中哪些是对象上的对象方法,哪些是类或非对象子例程(这是列出的子例程中最严重的问题/缺陷) 使用此方法,无法在子类中找到对象从超类继承的方法,除非已对对象调用了这些方法 这可以通过检查类的@ISA来进行编码 您找不到动态添加到类中的方法(自动加
- 您可以找到显式声明或放置在对象类命名空间中的子例程的名称
- 您无法区分这些子例程中哪些是对象上的对象方法,哪些是类或非对象子例程(这是列出的子例程中最严重的问题/缺陷)
- 使用此方法,无法在子类中找到对象从超类继承的方法,除非已对对象调用了这些方法
这可以通过检查类的
来进行编码@ISA
- 您找不到动态添加到类中的方法(自动加载,在代码中的某个地方手动注入方法)
UNIVERSAL::can
调用单独的子例程)
因此,如果您(通过非技术合同)保证类中100%的子例程是对象方法,并且您的类不是子类,那么您可以找到它们的列表
package MyClass;
use vars qw($z5);
my $x = 11; our $y = 12; $z5 = 14; %z2 = (1=>2); # my, our, globals, hash
sub new { return bless({}, $_[0]) }; # Constructor
sub x1 { my $self = shift; print $_[0]; };
sub y2 { my $self = shift; print $_[0]; };
##############################################################################
package MySubClass;
use vars qw(@ISA);
@ISA = ("MyClass");
sub z3 { return "" };
##############################################################################
package main;
use strict; use warnings;
my $obj = MyClass->new();
list_object_methods($obj);
my $obj2 = MySubClass->new();
list_object_methods($obj2);
$obj2->x1();
list_object_methods($obj2); # Add "x1" to the list!
sub list_object_methods {
my $obj = shift;
my $class_name = ref($obj);
no strict;
my @identifiers = keys %{"${class_name}::"};
use strict;
my @subroutines = grep { UNIVERSAL::can($obj, $_) } @identifiers;
print "Class: ${class_name}\n";
print "Subroutines: \n=========\n"
. join("\n", sort @subroutines) . "\n=========\n";
}
。。。印刷品:
Class: MyClass
Subroutines:
=========
new
x1
y2
=========
Class: MySubClass
Subroutines:
=========
new
z3
=========
Class: MySubClass
Subroutines:
=========
new
x1
z3
=========
请注意,第一次列表(对于MySubClass)是打印的new
和z3
,但不是x1
或y2
——因为new
已执行且z3
已在类中声明;但是x1
和y2
都不是,它们只是理论上继承的。但是,一旦我们执行了继承的x1
方法,第二个时间列表就包含了它,但仍然缺少继承的y2
sub s_print_obj {
my ($self, $arg1) = @_;
$s->{arg1} = $arg1;
print "$arg1\n";
}
# $obj->s_print_obj("XYZ") prints "XYZ" and stores the data in the object
sub s_print_class {
my ($class, $arg1) = @_;
print "Class: $class\n";
print "$arg1\n";
}
# $obj->s_print_class("XYZ") prints "Class: MyClass\nXYZ\n"
sub s_print_static {
my ($self, $arg1) = @_;
print "$arg1\n";
}
# $obj->s_print_static("XYZ") prints stringified representation of $obj
注意:事实上,有些人实际上编写了类的方法——那些可以以这种方式工作的方法——来显式地在所有3种(或前2种)情况下工作,而不管如何调用该方法DVK的答案是准确的,但有点冗长。简单的回答是可以,但您不知道什么是作为公共对象方法的,什么不是。可能会显示从其他模块导入的私有方法和函数 获取可调用的具体(即非自动加载)方法列表的最简单方法是使用的方法
这至少消除了大量代码。“您无法在子类中找到对象从超类继承的方法,除非它们已经在您的对象上被调用”。如果我没看错的话,你是说必须先运行
$obj->inherited\u方法
,然后才能发现inherited\u方法
?我不认为这是真的,也不可能奏效。有代码支持吗?@Schwern-参见该项目符号中的第二句话:“这可以通过检查类的ISA来构建继承树,或者使用适当的CPAN模块来进行编码。”。“cannot”部分指的是上面总结的直接读取名称空间散列的技术。这个语句的备份代码(没有你读过的那么夸张)是我在答案中的代码。我只是把walking@ISA
作为一个例子。方法如何区分对象的方法和类的非对象子类(参见第2部分中的3个示例)?POD似乎对此没有任何澄清。@DVK Simple:没有。正如你正确指出的,它不能。它只是列出了执行所有继承遍历和符号表检查的可用的、具体的、可调用的方法,所以您不必这样做。我将更正我答案中的几个代词,使之更清楚。它可以利用perl5i的func/method特性,但目前没有。您介意我将“方法列表”编辑为“子例程列表(方法与否)”吗?在具有OO功能的语言中,@DVK.:)
use perl5i::2;
my $object = Something::Something->new;
my @methods = $object->mo->methods;