我有一个程序在Perl中使用我从另一个来源得到的包。该方法的一个函数返回一个未知类的对象,有没有办法让我在不查看其类实现的情况下获取对象的所有可能方法?有没有办法知道在Perl中的未知类的实例的方法
回答
不是。
TL; DR:
你可以找到明确声明或置入对象的类的命名空间子程序的名字。
你无法区分这些子程序是你的对象对象的方法,哪些是类或非对象潜艇(这是那些上市中最严重的问题/ limintation)。
您不能从超类中使用此方法找到由子类中的对象继承的方法,除非已经在您的对象上调用它们。
这可以通过检查
@ISA
的类为build up inheritance trees, or using on of proper CPAN modules进行编码。您无法找到动态添加到类中的方法(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"; }
...打印:
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
。,但你不能,不幸的是,区分一个子程序,它是一个对象的方法(例如把它得到的对象的第一个参数),一个类的方法(例如把它得到一个类的第一个参数名称)或非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
注:由于事实上,一些人居然写自己的类的方法 - 那些能够以这种方式工作 - 在明确工作的所有3(或第一2)个案,不管该方法如何被调用。
DVK的答案是准确的,但有点冗长。简短的回答是,你可以,但是你不会知道什么是公共对象方法,什么不是。可能会显示从其他模块导入的私有方法和函数。
获取可调用的具体(即非AUTOLOAD)方法列表的最简单方法是使用perl5i meta object的methods()方法。
use perl5i::2;
my $object = Something::Something->new;
my @methods = $object->mo->methods;
至少消除了很多代码。
- 1. 有没有办法通过实例方法知道类名?红宝石
- 2. 有没有办法知道当前有多少个webrole实例?
- 3. VBA中有没有办法知道未使用的变量?
- 4. 有没有办法知道a-frame元素的“真实”位置?
- 5. 在Perl中:有没有办法知道列表中变量的名称?
- 6. 有没有办法知道调用方法?
- 7. 有没有办法处理未知的泛型类型?
- 8. 有没有办法知道自定义通知即将显示?
- 9. 有没有办法在C#中查看给定类实例的所有方法?
- 10. 有没有办法从Ruby中的实例调用私有的类方法?
- 11. 有没有办法知道,当有人导入附加的vCard?
- 12. 有没有办法知道在C++中调用对象的方法的类的名称?
- 13. 有没有办法从友好方面知道原始URL?
- 14. 有没有办法知道一个对象的C#方法是否被调用?
- 15. 有没有什么办法知道在javascript中扩展屏幕
- 16. 有没有办法知道HttpResponse是否在Https中?
- 17. 在PHP中 - 有没有办法知道fsockopen何时超时?
- 18. 有没有办法访问通知中心显示的通知?
- 19. 在Groovy中,有没有办法知道持有闭包的变量的名称?
- 20. 在谷歌实时,有没有办法知道复合操作是完整的?
- 21. 有没有办法知道激活的QAction是什么?
- 22. 有没有办法知道段落的高度?
- 23. 有没有办法知道谁是“setNeedsDisplay”的发件人?
- 24. 有没有办法知道返回的对象是什么?
- 25. 有没有办法知道整个UItableView的大小?
- 26. 有没有办法知道iOS上WiFI信号的强度
- 27. 有没有办法知道FBConnect的子女人数
- 28. 有没有办法知道navigator.geolocation coords的来源?
- 29. 有没有办法知道从UniversalLoader加载图像的位置?
- 30. 有没有办法让Sonarqube知道Jenkins的构建失败?
*“除非已经在对象上调用了对象,否则不能从超类的子类中找到对象所继承的方法”*。如果我正确地阅读了你的话,你应该说'$ obj-> inherited_method'必须运行才能找到'inherited_method'?我不认为这是真的,或[这些perl5i测试](https://metacpan.org/source/MSCHWERN/perl5i-v2.9.1/t/Meta/methods.t)不起作用。有代码来支持? – Schwern
@Schwern - 请参阅该子句中的第二句:“可以通过检查类的ISA来构建继承树或使用适当的CPAN模块来编码。” “不能”部分指的是直接读取命名空间哈希的上述总结技术。这个备份代码(比你读的更少),是我在答案中的代码。 – DVK
哦。我只是把'@ ISA'作为一个给定的行走。 – Schwern