2013-10-03 9 views
24

मुझे ओओ पर्ल और my $self = shift; के चौराहे को समझने में वास्तव में कठिन समय हो रहा है। इन व्यक्तिगत तत्वों पर प्रलेखन बहुत अच्छा है, लेकिन उनमें से कोई भी नहीं है कि मुझे यह पता चला कि वे एक साथ कैसे काम करते हैं।

मैं गुणों के साथ मॉड्यूल बनाने के लिए मूस का उपयोग कर रहा हूं, और निश्चित रूप से यह मॉड्यूल के भीतर मॉड्यूल की विशेषता को संदर्भित करने के लिए उपयोगी है। मुझे उस चर के मॉड्यूल के गुणों को असाइन करने के लिए एक सबराउटिन के भीतर my $self = shift; का उपयोग करने के लिए बार-बार कहा गया है। यह समझ में आता है और काम करता है, लेकिन जब मैं subroutine के लिए तर्क पारित कर रहा हूं, तो यह प्रक्रिया @ARGV सरणी का पहला तत्व स्पष्ट रूप से लेती है और इसे $self पर भी असाइन करती है।

क्या कोई इस बात का स्पष्टीकरण प्रदान कर सकता है कि मैं मॉड्यूल के गुणों में आंतरिक पहुंच प्राप्त करने के लिए शिफ्ट का उपयोग कैसे कर सकता हूं, जबकि @ARGV सरणी में तर्कों में गुजर रहा हूं?

उत्तर

52

सबसे पहले, एक subroutine @ARGV सरणी पारित नहीं किया गया है। इसके बजाय subroutine में पारित सभी पैरामीटर subroutine के अंदर @_ द्वारा प्रतिनिधित्व की गई एक सूची में चपटे हैं। @ARGV सरणी आपकी स्क्रिप्ट के शीर्ष-स्तर पर उपलब्ध है, जिसमें आपको स्क्रिप्ट में दिए गए कमांड लाइन तर्क शामिल हैं।

अब, पर्ल में, जब आप किसी ऑब्जेक्ट पर कोई विधि कॉल करते हैं, तो ऑब्जेक्ट को विधि के पैरामीटर के रूप में निहित रूप से पारित किया जाता है। @_ = ($obj, $a, $b);

अब

, shift निर्मित:

आप विरासत अनदेखा करते हैं,

$obj->doCoolStuff($a, $b); 

doCoolStuff($obj, $a, $b); 

के बराबर विधि में @_ की सामग्री doCoolStuff होगा जिसका मतलब है है फ़ंक्शन, बिना किसी पैरामीटर के, डी से तत्व को बदल देता है efault सरणी चर @_। इस मामले में, यह $obj होगा।

तो जब आप $self = shift करते हैं, तो आप प्रभावी ढंग से $self = $obj कह रहे हैं।

मुझे यह भी उम्मीद है कि यह बताता है कि -> नोटेशन के माध्यम से किसी विधि को अन्य पैरामीटर को कैसे पास किया जाए। उदाहरण मैं ऊपर कहा गया है गया है जारी रखते हुए, इस तरह होगा:

sub doCoolStuff { 
    # Remember @_ = ($obj, $a, $b) 
    my $self = shift; 
    my ($a, $b) = @_; 

इसके अतिरिक्त, जबकि Moose पर्ल के लिए एक महान वस्तु परत है, यह दूर की आवश्यकता है कि आप अपने आप को $self प्रारंभ करने की आवश्यकता से नहीं ले करता है प्रत्येक विधि में। हमेशा याद रखें। जबकि सी ++ और जावा जैसी भाषा ऑब्जेक्ट संदर्भ this को प्रारंभिक रूप से प्रारंभ करती है, पर्ल में आपको लिखने वाली प्रत्येक विधि के लिए इसे स्पष्ट रूप से करने की आवश्यकता होती है।

+2

'शिफ्ट' डिफ़ॉल्ट रूप से '@ _'' के लिए कहा जाता है, या उप-स्तर कोड से कॉल किया गया है, तो @ @ ARGV'। – cjm

+0

@cjm ठीक है आप हैं। जवाब में इसका उल्लेख करेंगे। – Nikhil

+0

बहुत बढ़िया। यह बहुत उपयोगी है। मैंने एक ऐसे मुद्दे में भाग लिया जहां मेरा $ self = shift खुद को पहले तर्क में स्थापित कर रहा था जिसे मैंने वास्तव में सबराउटिन में पारित किया था। हां, @_ में पहला तत्व ऑब्जेक्ट नहीं था, लेकिन वास्तव में मैंने जो पहला तर्क दिया था, वह वास्तव में था। यह कोई उच्च स्तर का कारण होगा? (मैंने इस समस्या के आसपास काम किया है और अब वास्तविक कोड नहीं है) –

8

शीर्ष स्तर-कोड में, shift()shift(@ARGV) के लिए छोटा है। @ARGV में कमांड-लाइन तर्क शामिल हैं।

उप में, shift()shift(@_) के लिए छोटा है। @_ में उप के तर्क शामिल हैं।

तो my $self = shift; उप के पहले तर्क को पकड़ रहा है।एक विधि को कॉल करते समय, invocant (-> के बाईं ओर क्या है) पहले पैरामीटर के रूप में पारित किया जाता है। दूसरे शब्दों में,

$o->method(@a) 

my $sub = $o->can('method'); 
$sub->($o, @a); 

कि उदाहरण में के समान है, my $self = shift;$self को $o आवंटित करेगा।

2

यदि आप कहते हैं:

$myinstance->myMethod("my_parameter"); 

एक ही है कि कर:

myMethod($myinstance, "my_parameter"); 

लेकिन यदि आप ऐसा:

myMethod("my_parameter"); 

केवल "my_parameter" पारित कर दिया हो जायेंगे।

फिर अगर MyMethod अंदर हमेशा आप कार्य करें:

$self = shift @_; 

$ स्वयं वस्तु संदर्भ जब MyMethod आईडी एक वस्तु संदर्भ से कहा जाता हो जाएगा
लेकिन जब एक पर अंदर एक और तरीका से बुलाया "my_parameter" हो जाएगा प्रक्रियात्मक तरीका।
इस बारे में जागरूक रहें;

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