संक्षिप्त उत्तर है: यदि आप उन्हें सुरक्षित रूप से उपयोग करते हैं तो यह सुरक्षित है :)
कर्कश उत्तर: मुझे बताएं कि आपके लक्षणों का क्या मतलब है, और शायद मैं आपको बेहतर उत्तर दूंगा :)
सभी गंभीरता में, शब्द "विशेषता" अच्छी तरह से परिभाषित नहीं है। कई जावा डेवलपर्स सबसे अधिक लक्षणों से परिचित हैं क्योंकि वे स्काला में व्यक्त किए गए हैं, लेकिन स्काला पहली भाषा से दूर या तो नाम या प्रभाव में है।
उदाहरण के लिए, स्काला में, लक्षण स्टेटफुल ( var
चर हो सकते हैं ); किले में वे शुद्ध व्यवहार करते हैं। डिफ़ॉल्ट विधियों के साथ जावा के इंटरफेस स्टेटलेस हैं; इसका मतलब यह है कि वे लक्षण नहीं हैं? (संकेत: यह एक ट्रिक प्रश्न था।)
फिर, स्काला में, रेखीयकरण के माध्यम से लक्षणों की रचना की जाती है; वर्ग अगर A
लक्षण फैली X
और Y
, फिर जिस क्रम में X
और Y
निर्धारित करता है में मिलाया जाता है कैसे के बीच संघर्ष X
और Y
हल कर रहे हैं। जावा में, यह रैखिककरण तंत्र मौजूद नहीं है (इसे अस्वीकार कर दिया गया था, भाग में, क्योंकि यह "संयुक्त राष्ट्र-जावा-जैसा था)" था।
इंटरफेस में डिफ़ॉल्ट तरीकों को जोड़ने के लिए अनुमानित कारण इंटरफ़ेस विकास का समर्थन करना था , लेकिन हम अच्छी तरह से जानते थे कि हम इससे परे जा रहे थे। क्या आप समझते हैं कि "इंटरफ़ेस विकास ++" या "लक्षण -" होना व्यक्तिगत व्याख्या का विषय है। इसलिए, सुरक्षा के बारे में आपके प्रश्न का उत्तर देने के लिए ... इसलिए जब तक आप वास्तव में तंत्र का समर्थन करते हैं, तब तक यह इच्छा करने की कोशिश करने के बजाय कि यह किसी चीज़ का समर्थन नहीं करता है, आपको ठीक होना चाहिए।
एक प्रमुख डिजाइन लक्ष्य यह था कि एक इंटरफ़ेस के क्लाइंट के दृष्टिकोण से , डिफ़ॉल्ट तरीकों को "नियमित" इंटरफ़ेस विधियों से अप्रभेद्य होना चाहिए। एक विधि का डिफ़ॉल्ट-नेस, इसलिए इंटरफ़ेस के डिजाइनर और कार्यान्वयन के लिए केवल दिलचस्प है ।
यहाँ कुछ उपयोग के मामले हैं जो डिज़ाइन लक्ष्यों के लिए ठीक हैं:
इंटरफ़ेस विकास। यहां, हम मौजूदा इंटरफ़ेस में एक नई विधि जोड़ रहे हैं, जिसमें उस इंटरफ़ेस पर मौजूदा विधियों के संदर्भ में एक समझदार डिफ़ॉल्ट कार्यान्वयन है। एक उदाहरण forEach
विधि को जोड़ना होगा Collection
, जहां iterator()
विधि के संदर्भ में डिफ़ॉल्ट कार्यान्वयन लिखा जाता है ।
"वैकल्पिक" तरीके। यहां, एक इंटरफ़ेस का डिज़ाइनर कह रहा है "कार्यान्वयनकर्ताओं को इस पद्धति को लागू करने की आवश्यकता नहीं है यदि वे कार्यक्षमता में सीमाओं के साथ रहने के लिए तैयार हैं जो प्रवेश करते हैं"। उदाहरण के लिए, Iterator.remove
एक डिफ़ॉल्ट दिया गया था जो फेंकता है UnsupportedOperationException
; Iterator
इस व्यवहार के कार्यान्वयन के विशाल बहुमत के बाद से , डिफ़ॉल्ट रूप से इस पद्धति को अनिवार्य रूप से वैकल्पिक बनाता है। (यदि इससे होने वाले व्यवहार AbstractCollection
को चूक के रूप में व्यक्त किया गया था Collection
, तो हम पारस्परिक तरीकों के लिए भी ऐसा कर सकते हैं।)
सुविधा के तरीके। ये ऐसी विधियाँ हैं जो कड़ाई से सुविधा के लिए हैं, फिर से आम तौर पर वर्ग पर गैर-डिफ़ॉल्ट विधियों के रूप में लागू की जाती हैं। logger()
आपके पहले उदाहरण में विधि इस का एक उचित चित्रण है।
Combinators। ये संरचनात्मक विधियाँ हैं जो वर्तमान उदाहरण के आधार पर इंटरफ़ेस के नए उदाहरणों को त्वरित करती हैं। उदाहरण के लिए, तरीके Predicate.and()
या Comparator.thenComparing()
संयोजन के उदाहरण हैं।
यदि आप एक डिफ़ॉल्ट कार्यान्वयन प्रदान करते हैं, तो आपको डिफ़ॉल्ट के लिए कुछ विनिर्देश प्रदान करना चाहिए (JDK में, हम इसके लिए @implSpec
javadoc टैग का उपयोग करते हैं ) कार्यान्वयनकर्ताओं को यह समझने में सहायता करने के लिए कि वे विधि को ओवरराइड करना चाहते हैं या नहीं। कुछ चूक, जैसे सुविधा के तरीके और कॉम्बिनेटर, लगभग कभी भी ओवरराइड नहीं होते हैं; अन्य, वैकल्पिक तरीकों की तरह, अक्सर ओवरराइड होते हैं। आपको डिफ़ॉल्ट का वादा करने के लिए पर्याप्त विनिर्देश (न केवल प्रलेखन) प्रदान करने की आवश्यकता है, इसलिए कार्यान्वयनकर्ता इस बारे में एक समझदार निर्णय ले सकता है कि क्या उन्हें इसे ओवरराइड करने की आवश्यकता है।