2009-01-09 25 views
27

कई साल पहले मैं एक साथी प्रोग्रामर इस परामर्श याद रखें:पर्ल में नए कुछ :: कक्षा और कुछ :: कक्षा-> नया() के बीच क्या अंतर है?

new Some::Class; # bad! (but why?) 

Some::Class->new(); # good! 

दुर्भाग्य से अब मैं/उसके कारण है कि याद नहीं कर सकते। :(दोनों फॉर्म सही ढंग से काम करेंगे, भले ही कन्स्ट्रक्टर वास्तव में कुछ :: कक्षा मॉड्यूल में मौजूद न हो, लेकिन इसके बजाय माता-पिता से कहीं भी विरासत में मिला है।

इनमें से कोई भी रूप कुछ :: क्लास :: नया जैसा नहीं है(), जो वर्ग के नाम को कन्स्ट्रक्टर के पहले पैरामीटर के रूप में पास नहीं करेगा - इसलिए यह फॉर्म हमेशा गलत है।

भले ही दोनों रूप बराबर हैं, मुझे कुछ :: कक्षा-> नया () अधिक स्पष्ट होने के लिए, क्योंकि यह मॉड्यूल पर एक विधि को कॉल करने के लिए मानक सम्मेलन का पालन करता है, और पर्ल में, 'नई' विधि विशेष नहीं है - एक निर्माता को कुछ भी कहा जा सकता है, और नया() कुछ भी कर सकता है (हालांकि बेशक हम आम तौर पर इसे एक निर्माता बनने की उम्मीद करते हैं)

+0

एक और उत्कृष्ट संदर्भ: [अप्रत्यक्ष लेकिन अभी भी घातक] (http://www.shadowcat.co.uk/blog/matt-s-trout/indirect-but-still-fatal/) – Ether

उत्तर

26

new Some::Class का उपयोग करके "अप्रत्यक्ष" विधि आमंत्रण कहा जाता है, और यह बुरा है क्योंकि यह वाक्यविन्यास में कुछ अस्पष्टता प्रस्तुत करता है।

एक कारण यह विफल हो सकता है यदि आपके पास ऑब्जेक्ट्स का सरणी या हैश है। आप

dosomethingwith $hashref->{obj} 

$hashref->{obj}->dosomethingwith(); 

के बराबर होना चाहिए उम्मीद कर सकते हैं लेकिन यह वास्तव में के रूप में पार्स करता है: जो शायद नहीं है कि तुम क्या चाहते थे

$hashref->dosomethingwith->{obj} 

एक और समस्या यह है कि यदि आपके पैकेज में एक ऐसा फ़ंक्शन होता है जिसे आप कॉल करने का प्रयास कर रहे हैं। उदाहरण के लिए, यदि कुछ मॉड्यूल जो आपने use 'डी dosomethingwith नामक फ़ंक्शन को निर्यात किया है? उस स्थिति में, dosomethingwith $object संदिग्ध है, और परिणामस्वरूप परेशान बग हो सकता है।

-> सिंटैक्स का उपयोग करके इन समस्याओं को विशेष रूप से समाप्त कर दिया जाता है, क्योंकि विधि और आप जिस पर काम करने की विधि चाहते हैं वह हमेशा कंपाइलर को स्पष्ट होता है।

21

अपने नुकसान के स्पष्टीकरण के लिए perlobj दस्तावेज़ में Indirect Object Syntax देखें। freido's answer उनमें से एक को शामिल करता है (हालांकि मैं अपने फ़ंक्शन कॉल के आस-पास स्पष्ट अभिभावकों से बचने के लिए प्रयास करता हूं)।

लैरी ने एक बार मजाक किया कि सी ++ new के बारे में खुश महसूस करने के लिए वहां था, और हालांकि लोग आपको कभी भी इसका उपयोग न करने के लिए कहेंगे, आप शायद इसे हर समय कर रहे हैं। इस पर विचार करें:

print FH "Some message"; 

आपने कभी सोचा कि मेरी वहाँ filehandle के बाद कोई अल्पविराम था? और अप्रत्यक्ष वस्तु नोटेशन में कक्षा के नाम के बाद कोई अल्पविराम नहीं है? यह वही है जो यहां जा रहा है। आप को फिर से लिखने सकता है कि प्रिंट पर एक विधि कॉल के रूप में:

FH->print("Some message"); 

आप print में कुछ weirdness अनुभव हो सकता है यदि आप गलत करते हैं। स्पष्ट फ़ाइल हैंडल के बाद एक अल्पविराम लाना एक बहस में बदल जाता:

print FH, "some message";  # GLOB(0xDEADBEEF)some message 

दुख की बात है, हम पर्ल में इस goofiness है। सिंटैक्स में जो कुछ भी मिला वह सबसे अच्छा विचार नहीं था, लेकिन यह तब होता है जब आप प्रेरणा के लिए इतने सारे स्रोतों से खींचते हैं। कुछ विचारों को बुरे होना चाहिए।

+7

मैंने यह नहीं पढ़ा है वर्षों में आदमी पेज; मुझे वास्तव में इसे और अधिक पढ़ना चाहिए। यह एक शर्म की बात है 'नई कुछ :: कक्षा' में इतनी सारी समस्याएं हैं, क्योंकि मुझे 'कुछ :: कक्षा-> नया()' से बेहतर तरीके से पढ़ना पसंद है; पर्ल के बारे में मुझे सबसे ज्यादा पसंद है, इसमें से एक प्राकृतिक भाषा है। ओह ठीक है, बदलाव के लिए समय ..... –

4

अप्रत्यक्ष ऑब्जेक्ट सिंटैक्स अच्छे कारणों से फंस गया है, लेकिन रचनाकारों के साथ इसका कोई लेना-देना नहीं है। आप कॉलिंग पैकेज में लगभग एक नया() फ़ंक्शन नहीं ले रहे हैं। बल्कि, आप पैकेज>() दो अन्य (? बेहतर) कारणों के लिए इस्तेमाल करना चाहिए नया:

  1. जैसा कि आपने कहा, अन्य सभी वर्ग के तरीकों प्रपत्र पैकेज ले> विधि(), इसलिए स्थिरता एक अच्छा है चीज

  2. यदि आप निर्माता को तर्क दे रहे हैं, या आप कन्स्ट्रक्टर का परिणाम ले रहे हैं और तुरंत इसके बारे में कॉलिंग कर रहे हैं (यदि उदाहरण के लिए आप ऑब्जेक्ट को चारों ओर रखने की परवाह नहीं करते हैं), तो यह आसान है उदाहरण के लिए कहो

$foo = Foo->new(type => 'bar', style => 'baz'); 
Bar->new->do_stuff; 

से

$foo = new Foo(type => 'bar', style => 'baz'); 
(new Bar)->do_stuff; 
-3

एक और समस्या यह है कि new Some::Class रन टाइम पर होता है। यदि कोई त्रुटि है और आप कभी भी इस कथन में शाखाओं का परीक्षण नहीं करते हैं, तो आप इसे तब तक नहीं जानते जब तक उत्पादन में ऐसा न हो। जब तक आप गतिशील प्रोग्रामिंग नहीं कर रहे हैं, तब तक Some::Class->new का उपयोग करना बेहतर है।

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