我在Perl中有一个程序,它使用我从其他来源获得的包.该方法的一个函数返回一个未知类的对象,有没有办法让我获得一个对象的所有可能方法,而无需查看它的类实现?
并不是的.
TL; DR:
您可以找到显式声明或放入对象类的命名空间的子例程的名称.
您无法区分哪些子例程是对象上的对象方法,哪些是类或非对象子(这是列出的最严重的问题/限制).
除非已在对象上调用它们,否则您无法使用此方法找到超类中子对象继承的方法.
这可以通过检查@ISA
类来构建继承树或使用适当的CPAN模块来编码.
您无法找到动态添加到类中的方法(AUTOLOAD,代码中的手动方法注入).
详细地
您可以在该类中找到所有子例程(通过组合类命名空间是哈希的事实,因此其中的所有标识符都是该哈希中的键;以及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";
}
Run Code Online (Sandbox Code Playgroud)
...打印:
Class: MyClass
Subroutines:
=========
new
x1
y2
=========
Class: MySubClass
Subroutines:
=========
new
z3
=========
Class: MySubClass
Subroutines:
=========
new
x1
z3
=========
Run Code Online (Sandbox Code Playgroud)
请注意,第一次列表(MySubClass)印刷new
和z3
,但不x1
还是y2
-因为new
被执行,并z3
在课堂上被宣布; 但x1
与y2
既不是-他们仅仅是理论上的继承.但是,一旦我们执行了一个继承的x1
方法,那么第二次列表就会包含它,但仍然缺少继承的方法y2
.
但遗憾的是,您不能区分作为对象方法的子例程(例如,将它作为对象获取的第一个参数),类方法(例如将其作为类名称获取的第一个参数)或非OO子元素区分开来. (将第一个参数视为常规参数).
为了区分3,唯一的方法是实际上在语义上分析代码.否则,你无法区分:
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
Run Code Online (Sandbox Code Playgroud)
注意:事实上,有些人实际上写了他们的类的方法 - 那些可以这样工作的方法 - 明确地工作在ALL 3(或前2)的情况下,无论方法如何被调用.
归档时间: |
|
查看次数: |
117 次 |
最近记录: |