2012-06-03 6 views
5

में अज्ञात वर्ग के उदाहरण के तरीकों को जानने का कोई तरीका है मेरे पास पर्ल में एक प्रोग्राम है जो मुझे किसी अन्य स्रोत से प्राप्त पैकेज का उपयोग करता है। विधि के कार्यों में से एक अज्ञात वर्ग का एक वस्तु देता है, क्या मेरे वर्ग कार्यान्वयन को देखे बिना किसी ऑब्जेक्ट के सभी संभावित तरीकों को प्राप्त करने का कोई तरीका है?पर्ल

उत्तर

9

वास्तव में नहीं।

टी एल; डॉ:

  • आप सबरूटीन्स स्पष्ट रूप से घोषित या वस्तु की क्लास का नाम स्थान में रखा के नाम पा सकते हैं।

  • आप भेद नहीं कर सकते जो इन सबरूटीन्स के अपने वस्तु पर वस्तु तरीके हैं, और जो वर्ग या गैर वस्तु बाद के चरणों (यह सबसे गंभीर समस्या/सूचीबद्ध उन लोगों के बीच limintation है) कर रहे हैं।

  • आप सुपर क्लास से उपवर्ग में एक वस्तु द्वारा विरासत में मिली तरीकों इस विधि, जब तक वे पहले से ही अपने वस्तु पर कहा जाता था का उपयोग कर नहीं पा सकते हैं।

    कक्षा के @ISA को कक्षा में build up inheritance trees, or using on of proper CPAN modules पर निरीक्षण करके इसे कोड किया जा सकता है।

  • आप कक्षाओं में गतिशील रूप से जोड़े गए तरीकों को नहीं ढूंढ सकते हैं (ऑटोलोड, मैन्युअल विधि इंजेक्शन कहीं भी कोड में)।

विस्तार में

  1. आप तथ्य यह है कि वर्ग नाम स्थान एक हैश है संयोजन से उस वर्ग में सबरूटीन्स (के सभी पा सकते हैं तो यह सभी पहचानकर्ता कि हैश में चाबियाँ हैं ; और UNIVERSAL::can subroutines अलग करने के लिए कॉल)।

    इसलिए, यदि आप गारंटीकृत हैं (गैर-तकनीकी अनुबंध द्वारा) कि कक्षा में 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


  2. लेकिन तुम नहीं, दुर्भाग्य से, एक सबरूटीन एक वस्तु तरीका है कि भेद कर सकते हैं, एक वर्ग विधि (जैसे पहला तर्क यह एक वस्तु के रूप में हो जाता है व्यवहार करता है) (जैसे पहला तर्क यह एक वर्ग के रूप में हो जाता है व्यवहार करता है नाम) या एक गैर-ओओ उप (नियमित तर्क के रूप में पहला तर्क माना जाता है)।

    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) मामलों, कोई फर्क नहीं पड़ता कि विधि कैसे कहा जाता है।

+0

* "आप सुपरक्लास से उप-वर्ग में किसी ऑब्जेक्ट द्वारा विरासत में प्राप्त विधियों को नहीं ढूंढ सकते हैं, जब तक कि वे पहले से ही आपके ऑब्जेक्ट पर नहीं बुले गए" *। यदि मैं आपको सही तरीके से पढ़ रहा हूं, तो आप कह रहे हैं कि 'विरासत_एम विधि' को स्थानांतरित करने से पहले आप $ $ obj-> विरासत_method' चलाना चाहते हैं? मुझे नहीं लगता कि यह सच है या [इन perl5i परीक्षण] (https://metacpan.org/source/MSCHWERN/perl5i-v2.9.1/t/Meta/methods.t) काम नहीं करेगा। उस कोड को वापस पाने के लिए कोड मिला? – Schwern

+0

@ स्क्वार्न - उस बुलेट में दूसरी वाक्य देखें: "यह विरासत पेड़ बनाने या उचित सीपीएएन मॉड्यूल के उपयोग के लिए कक्षा के आईएसए का निरीक्षण करके चारों ओर कोड किया जा सकता है।" "नहीं कर सकता" भाग नामस्थान हैश को सीधे पढ़ने की उपर्युक्त तकनीक का जिक्र कर रहा था। इस के लिए बैक अप कोड (कम से कम ग्रैंडहाउस इसे पढ़ने से) कथन उत्तर में मेरा कोड है। – DVK

+0

ओह। मैंने अभी दिए गए के रूप में 'आईएसए' चलना लिया। – Schwern

0

डीवीके का उत्तर सटीक है, लेकिन थोड़ा लंबा है। संक्षिप्त उत्तर यह है कि आप कर सकते हैं, लेकिन आप नहीं जान पाएंगे कि सार्वजनिक वस्तु विधि के रूप में क्या उद्देश्य था और क्या नहीं था। अन्य मॉड्यूल से आयातित निजी विधियों और कार्यों को दिखाया जा सकता है।

कॉल करने योग्य, कंक्रीट (यानी गैर-ऑटोोलॉइड) विधियों की सूची प्राप्त करने का सबसे आसान तरीका perl5i meta object की methods() विधि का उपयोग करना है।

use perl5i::2; 

my $object = Something::Something->new; 
my @methods = $object->mo->methods; 

कम से कम बहुत सारे कोड को समाप्त करता है।

+0

'विधियों' ऑब्जेक्ट के तरीकों और कक्षा के गैर-ऑब्जेक्ट सब के बीच अंतर कैसे करता है (भाग 3 में मेरे 3 उदाहरण देखें)? पीओडी पर उस पर कोई स्पष्टीकरण नहीं प्रतीत होता था। – DVK

+0

इसके अलावा, क्या यह स्वचालित रूप से ऑटोलोडेड सामान के साथ सौदा करता है? – DVK

+0

@ डीवीके सरल: यह नहीं है। जैसा कि आपने सही ढंग से बताया है, यह नहीं कर सकता है। यह सिर्फ उपलब्ध, ठोस, कॉल करने योग्य विधियों को सूचीबद्ध करता है जो सभी विरासत चलने और प्रतीक तालिका परीक्षा कर रहे हैं, इसलिए आपको यह नहीं करना है। मैं यह स्पष्ट करने के लिए अपने उत्तर में कुछ सर्वनाम सही कर दूंगा। यह * perl5i के func/विधि भेद का लाभ उठा सकता है, लेकिन वर्तमान में यह नहीं करता है। – Schwern