Scala संकलक पैटर्न को मिलान वाली कक्षाओं / लक्षणों के लिए चेतावनी क्यों नहीं दे सकता है?


10

अगर मैं एक संयुक्त सील traitया abstract classस्काला का उपयोग करता हूं और फिर पैटर्न मिलान का उपयोग करता हूं, तो मुझे आश्चर्य है कि क्या कंपाइलर को इस विशेष पैटर्नमैच के लिए संकलन समय पर नहीं पता है कि इस विशेषता / वर्ग के संभावित कार्यान्वयन क्या उपलब्ध हैं? इसलिए, अगर ऐसा होता है, तो क्या यह पैटर्न मैच की चेतावनी नहीं दे सकता है, भले ही यहtrait / abstract classको सील नहीं किया गया हो, क्योंकि वह जानता है कि किस प्रकार का उपयोग किया जा सकता है, सभी संभव निर्भरता / आयात की जांच करके?

जैसे अगर मैं ए Option[A] और मैं केवल उसी के लिए पैटर्न मिलान करता हूं, Some[A]लेकिन नहीं None, तो कंपाइलर शिकायत करेगा, क्योंकि Optionसील है।

यदि संकलक यह नहीं जान सकता / हल कर सकता है, तो वह क्यों नहीं कर सकता है? और यदि कंपाइलर (सैद्धांतिक रूप से) ऐसा कर सकता है, तो इसके क्या कारण हैं कि इसका उपयोग स्काला में नहीं किया जाता है? क्या अन्य भाषाएँ हैं जो इस तरह के व्यवहार का समर्थन करती हैं?


यह स्पष्ट नहीं है कि आप क्या पूछ रहे हैं। क्या आप चाहते हैं कि कंपाइलर एक चेतावनी का उत्सर्जन करे अगर मैच एक्सप्रेशन सभी संभावित इनपुट्स को कवर नहीं करता है? शायद एक उदाहरण आपके प्रश्न को और स्पष्ट कर देगा।
kdgregory

2
यदि कोई नया उपवर्ग पेश कर सकता है, तो पैटर्न मिलान कभी भी विस्तृत नहीं हो सकता है। उदाहरण के लिए आप कुछ अमूर्त वर्ग का उत्पादन Fooउपवर्गों के साथ A, B, और C, और अपने पैटर्न मैचों में से सभी के लिए केवल उन तीन से मेल खाते हैं। कुछ भी नहीं मुझे एक नया उपवर्ग जोड़ने से रोकता है Dजो आपके पैटर्न मैचों को उड़ा देगा।
डोभाल

@kdgregory हां, आपको मिल गया। मैंने इसे और अधिक स्पष्ट करने के लिए एक उदाहरण जोड़ा।
वलंटेरी 12

3
सभी आयात की जाँच करना सभी संभव उपवर्गों की खोज करने के लिए पर्याप्त नहीं है। एक अन्य उपवर्ग को एक अलग श्रेणी फ़ाइल में घोषित किया जा सकता है जिसे बाद में रनटाइम के दौरान लोड किया जाता है java.lang.ClassLoader
आमोन

जवाबों:


17

किसी वर्ग के सभी उपवर्गों का पता लगाना कक्षा पदानुक्रम विश्लेषण कहलाता है और डायनेमिक कोड लोडिंग वाली भाषा में स्थिर CHA करना हॉल्टिंग समस्या को हल करने के बराबर है।

इसके अलावा, स्काला के लक्ष्यों में से एक अलग संकलन और स्वतंत्र मॉड्यूलों की तैनाती है, इसलिए कंपाइलर को यह पता नहीं चल सकता है कि एक वर्ग दूसरे मॉड्यूल में उप-वर्ग है या नहीं, क्योंकि यह कभी भी एक से अधिक मॉड्यूल को नहीं देखता है। (आखिरकार, आप उस मॉड्यूल के बिना किसी अन्य मॉड्यूल के इंटरफेस के खिलाफ एक मॉड्यूल को संकलित कर सकते हैं जो आपके सिस्टम पर भी मौजूद है!) यही कारण हैsealed सभी उपवर्गों को एक ही संकलन इकाई में परिभाषित करने की आवश्यकता होती है।

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

नोट: यह सब केवल स्काला के भीतर लागू होता है। जेवीएम की कोई धारणा नहीं है sealed, इसलिए किसी अन्य जेवीएम भाषा sealedसे कक्षाओं को उप- वर्ग करना पूरी तरह से संभव है , क्योंकि इसे किसी अन्य भाषा में संचार करने का कोई तरीका नहीं है। संपत्ति में दर्ज की गई है एनोटेशन, लेकिन अन्य भाषाओं 'compilers खाते में उन एनोटेशन नहीं लेते, जाहिर है।sealedScalaSig


3

यह किया जा सकता है (कम से कम संकलन के समय ज्ञात सभी वर्गों के लिए), यह सिर्फ महंगा है। आप वृद्धिशील संकलन को पूरी तरह से नष्ट कर देंगे, क्योंकि पैटर्न मैच से जुड़ी हर चीज को प्रभावी रूप से हर बार किसी अन्य फ़ाइल को बदलने के लिए फिर से तैयार करना होगा।

और आप क्या खरीद रहे हैं? यह पैटर्न मिलान लिखने के लिए एक कोड गंध है जिसे एक नए व्युत्पन्न वर्ग को जोड़ने पर अक्सर बदलने की आवश्यकता होती है। यह खुले / बंद सिद्धांत का उल्लंघन है । इनहेरिटेंस का ठीक से उपयोग करें और आपको उन प्रकार के पैटर्न मैचों को लिखने की आवश्यकता नहीं होगी। और हाँ, खुले / बंद सिद्धांत भी वर्ग-आधारित विरासत के बिना कार्यात्मक भाषाओं पर लागू होते हैं। वास्तव में टाइप क्लास, मल्टीमिथोड्स और सिर्फ सादे उच्च-क्रम के कार्यों जैसी सुविधाओं के बीच, कार्यात्मक भाषाएं बिना संशोधन के विस्तार को बहुत आसान बना देती हैं।


1
It can be done (at least for all classes known at compile time), it's just expensive.लेकिन अगर कार्यक्रम 100% स्व-निहित नहीं है (यानी यह बाहरी .jarफ़ाइलों पर निर्भर करता है ), तो क्या आप एस में से एक के माध्यम से संकलन के बाद एक नए उपवर्ग में चुपके नहीं कर सकते jar? इसलिए कंपाइलर आपको बता सकता है कि "आपके पैटर्न के मैच अब समाप्त हो गए हैं, लेकिन अगर आपकी कोई निर्भरता बदल जाए तो यह बदल सकता है" जो कि बहुत ही बेकार है क्योंकि बाहरी निर्भरता होने की बात यह है कि उन्हें पुन: स्थापित किए बिना अपडेट करने में सक्षम होना चाहिए!
डोभाल

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

@ डोभाल तब आपको प्रतिनिधि के कुछ रूप का उपयोग करना चाहिए और वर्ग को यह निर्णय लेने देना चाहिए कि क्या करना है और नियंत्रण को उलटना है। यह वही है जो OOP के लिए था। यदि आप ऐसा नहीं चाहते हैं तो आपके पास अपना वर्तमान मुद्दा है।
स्लेज

@ArtB मैं यह देखने में विफल रहता हूं कि नियंत्रण के प्रतिनिधिमंडल या व्युत्क्रम का इससे क्या लेना-देना है।
डोभाल

यदि आप चाहते हैं कि इसे बाहरी रूप से जोड़ने में सक्षम लोगों के साथ काम करें, तो कक्षा को कॉल करें और उन कक्षाओं में तर्क को स्थानांतरित करें।
स्लेज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.