2009-09-01 17 views
14

क्या आप पर्ल में एक विधि कॉल को रोक सकते हैं, तर्कों के साथ कुछ कर सकते हैं, और फिर इसे निष्पादित कर सकते हैं?क्या पर्ल विधि कॉल को अवरुद्ध किया जा सकता है?

+1

मुझे लगता है कि आपने टैग "एओपी" का उपयोग किया था। आप उन विशिष्ट एओपी तकनीकों के बारे में क्यों नहीं पूछें जिनका आप उपयोग करना चाहते हैं? (आपके प्रश्न के उत्तर आपको एओपी सिस्टम को लागू करने में मदद कर सकते हैं, लेकिन ऐसा क्यों करते हैं जब किसी और ने इसे पहले ही कर लिया हो?) – jrockway

+0

मैंने सोचा कि यह विधि विशेषताओं के साथ किया जा सकता है, लेकिन अब मुझे उपयुक्त पेल्डोक पेज नहीं मिला है (perldoc विशेषताएँ वह पृष्ठ नहीं है जिसके बारे में मैं सोच रहा था)। मुझे लॉगिंग में जोड़ने के लिए विभिन्न विधियों को लपेटने का एक अच्छा उदाहरण याद है ... – Ether

+0

अतिरिक्त जानकारी के लिए इस संबंधित SO प्रश्न को देखें: http://stackoverflow.com/questions/635212/how-i-redefine-perl-class-methods – draegtun

उत्तर

14

हां, आप पर्ल सबराउटिन कॉल को रोक सकते हैं। मेरे पास Mastering Perl में उस तरह की चीज़ के बारे में एक संपूर्ण अध्याय है। Hook::LexWrap मॉड्यूल देखें, जो आपको सभी विवरणों के बिना इसे करने देता है। पर्ल के तरीके सिर्फ subroutines हैं।

आप एक उप-वर्ग भी बना सकते हैं और उस विधि को ओवरराइड कर सकते हैं जिसे आप पकड़ना चाहते हैं। ऐसा करने का यह थोड़ा बेहतर तरीका है क्योंकि ऑब्जेक्ट उन्मुख प्रोग्रामिंग यह है कि आप इसके साथ ऐसा करें। हालांकि, कभी-कभी लोग कोड लिखते हैं जो आपको इसे ठीक से करने की अनुमति नहीं देता है। Mastering Perl में इसके बारे में और भी कुछ है।

6

यह Moose के लिए नौकरी की तरह दिखता है! मूस पर्ल के लिए एक ऑब्जेक्ट सिस्टम है जो ऐसा कर सकता है और बहुत कुछ। docs मैं जितना कर सकता हूं उसे समझाते हुए एक बेहतर काम करेगा, लेकिन आप जो चाहते हैं वह Method Modifier है, विशेष रूप से before

+1

मूस कुछ ऐसा है जो आप पूरे आवेदन के लिए उपयोग करते हैं, लक्षित समस्याओं नहीं। –

+3

लेकिन यह इस बात पर निर्भर करता है कि समस्या क्या है, और प्रश्न के पूछताछ में कोई विवरण नहीं है। यह हो सकता है कि कोई नया आवेदन बनाने के लिए एक दृष्टिकोण का मूल्यांकन कर रहा हो, जिसमें मूस पर मामला चालू किया जा रहा है, यह उचित और फायदेमंद प्रतिक्रिया होगी। – jsoverson

+1

हमने अभी भी वही बात कहा है। मैंने मूस का उपयोग न करने का नहीं कहा, लेकिन मैंने इसका इस्तेमाल करने के लिए भी नहीं कहा। –

7

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

# The subroutine we'll interrupt calls to 
sub call_me 
{ 
    print shift,"\n"; 
} 

# Intercepting factory 
sub aspectate 
{ 
    my $callee = shift; 
    my $value = shift; 
    return sub { $callee->($value + shift); }; 
} 
my $aspectated_call_me = aspectate \&call_me, 100; 

# Rewrite symbol table of main package (lasts to the end of the block). 
# Replace "main" with the name of the package (class) you're intercepting 
local *main::call_me = $aspectated_call_me; 

# Voila! Prints 105! 
call_me(5); 

यह भी पता चलता है कि, एक बार किसी को सबरूटीन के संदर्भ लेता है और संदर्भ के माध्यम से यह कहता है, आप अब इस तरह के कॉल को प्रभावित कर सकते हैं: इस दृष्टिकोण को दर्शाता है।

मुझे पूरा यकीन है कि पर्ले में पहलू करने के लिए ढांचे हैं, लेकिन मुझे आशा है कि दृष्टिकोण का प्रदर्शन होगा।

3

हां। @_ में हैं जो सिर्फ एक और गतिशील scoped चर रहा है एक कॉल करने के लिए

तर्क:

आपको तीन कार्य की जरूरत है।

फिर, goto एक संदर्भ-उप तर्क का समर्थन करता है जो वर्तमान @_ को संरक्षित करता है लेकिन एक और (पूंछ) फ़ंक्शन कॉल करता है।

अंत में local का उपयोग अक्षीय रूप से स्कॉप्ड वैश्विक चर बनाने के लिए किया जा सकता है, और प्रतीक तालिका %:: में दफन की जाती है।

तो तुम मिल गया है:

sub foo { 
    my($x,$y)=(@_); 
    print "$x/$y = " . ((0.0+$x)/$y)."\n"; 
} 
sub doit { 
    foo(3,4); 
} 
doit(); 

जो निश्चित रूप से प्रिंट आउट:

3/4 = 0.75 

हम local का उपयोग कर foo की जगह और जा सकते हैं:

my $oldfoo = \&foo; 
local *foo = sub { (@_)=($_[1], $_[0]); goto $oldfoo; }; 
doit(); 

और अब हम मिल :

4/3 = 1.33333333333333 

आप इसके नाम का उपयोग किए बिना *foo संशोधित करने के लिए करना चाहता था, और आप, %:: जोड़ तोड़ द्वारा eval उपयोग करने के लिए उदाहरण के लिए, तो आप इसे संशोधित कर सकता है नहीं करना चाहता था:

$::{"foo"} = sub { (@_)=($_[0], 1); goto $oldfoo; }; 
doit(); 

और अब हम पाते हैं:

3/1 = 3 
5

आप कर सकते हैं, और पावेल इसे करने का एक अच्छा तरीका बताते हैं, लेकिन आपको शायद यह बताएं कि आप इसे पहले स्थान पर क्यों करना चाहते हैं।

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

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

उदा।

use Data::Dumper; 

sub Dumper { 
    warn 'Dumping variables'; 
    print Data::Dumper::Dumper(@_); 
} 

my $foo = { 
    bar => 'barval', 
}; 

Dumper($foo); 

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

+1

इस मामले में, आपको डम्पर को खाली आयात सूची देना चाहिए ताकि आप कुछ भी आयात न करें। इसके अलावा, अनुक्रम इस मामले में मायने रखता है। आपको पहले आयात करना होगा, फिर ओवरराइड करना होगा। अंतिम subroutine परिभाषा जीतता है। अंत में, चेतावनियों के तहत, आपको यह करने में 'redefine' त्रुटि मिल जाएगी। –

+0

निश्चित रूप से, उदाहरण के लिए इसे सरल रखने की कोशिश कर रहा है। प्रत्येक स्पर्शिक विस्तार को समझाने के बजाय प्रत्यक्ष होने के कारण अधिक मूल्य (और उत्तरदाता के लिए तेज़ है)। आयात और चेतावनियों की अवधारणाओं को वैसे भी अन्य प्रश्नों के रूप में समझाया जाएगा। – jsoverson

संबंधित मुद्दे