我有一個程序在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