जावा इंटरफ़ेस में निजी सदस्यों को अनुमति क्यों नहीं देता है?


87

जावा इंटरफ़ेस में निजी सदस्यों को अनुमति क्यों नहीं देता है? क्या इसकी कोई खास वजह है?


@pst मैंने अपने उत्तर के अंत में एक वर्कअराउंड लिखा है - stackoverflow.com/a/10169894/348975 । क्या यह आपकी चिंताओं को दूर करता है?
एमोरी

जावा 9 इसके बाद की अनुमति दी। नीचे मेरे जवाब की जाँच करें: stackoverflow.com/questions/10169654/…
akhil_mittal

जवाबों:


87

से जावा भाषा युक्ति, (अभिगम नियंत्रण) :

"जावा प्रोग्रामिंग भाषा किसी पैकेज या वर्ग के उपयोगकर्ताओं को उस पैकेज या वर्ग के कार्यान्वयन के अनावश्यक विवरणों के आधार पर रोकने के लिए अभिगम नियंत्रण के लिए तंत्र प्रदान करती है।"

पहुँच नियंत्रण सभी कार्यान्वयन विवरणों को छिपाने के बारे में है। एक इंटरफ़ेस में छिपाने के लिए कोई कार्यान्वयन नहीं है।


9
चूँकि हम एक इंटरफ़ेस के अंदर घोंसले की कक्षाएं लगा सकते हैं, इसलिए हम इंटरफ़ेस पर कार्यान्वयन कर सकते हैं। ऐसा करना बहुत गलत है, लेकिन हम कर सकते हैं।
एमोरी

29
जावा 9 इंटरफ़ेस में निजी तरीकों की अनुमति देता है, यह डिफ़ॉल्ट तरीकों के अलावा के बाद तार्किक है, Ref: Bugs.openjdk.java.net/browse/JDK-8071453
हरिहरन

3
"ऐसा करना बहुत गलत है" .. हमेशा की तरह, संदर्भ पर निर्भर करता है।
JacksOnF1re

5
यह उतना बुरा नहीं है जितना लगता है। एक इंटरफ़ेस में निजी तरीके केवल उसी इंटरफ़ेस में डिफ़ॉल्ट विधियों द्वारा सुलभ हो सकते हैं। एक लाभ यह है कि इनकैप्सुलेशन को तोड़ने के बिना डिफ़ॉल्ट छोटे कार्यों में डिफ़ॉल्ट तरीकों के कार्यान्वयन में मदद करना।
हेनरी फाम

48

जावा 9 में, इंटरफेस में निजी तरीके संभव हैं।

जावा 9 विनिर्देशों

Javac कंपाइलर टीम JDK के 9 b54 बिल्ड से शुरू होने वाले इंटरफेस में निजी तरीकों के लिए कंपाइलर समर्थन की उपलब्धता की घोषणा करते हुए प्रसन्न है।


10
@SebiSebi, जब आपको जावा का एहसास होता है तो वह एक जीवंत भाषा होती है।
अरासॉफ्ट

@Arashsoft, ओपी खेतों के लिए पूछ रहा है।
पचेरियर

19

JEP-213 के भाग के रूप में निजी इंटरफ़ेस विधियाँ जावा 9 का हिस्सा हैं । चूंकि जावा 8 में इंटरफेस में डिफ़ॉल्ट तरीके हो सकते हैं , इसलिए निजी तरीके साझा निजी पद्धति का उपयोग करने के लिए कई डिफ़ॉल्ट तरीकों की अनुमति देते हैं।


13

जावा 8 के रूप में, इंटरफेस में डिफ़ॉल्ट तरीके हो सकते हैं, और जावा 9 के रूप में, एक इंटरफ़ेस में एक निजी तरीके की अनुमति होती है जिसे केवल उसी तरीके से डिफ़ॉल्ट तरीकों से एक्सेस किया जा सकता है।


जावा -9 इंटरफ़ेस सुविधाओं के बारे में जानने के लिए अच्छा है।
रवींद्र बाबू

9

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


जावा भूमि में, एक सदस्य एक क्षेत्र, विधि, निर्माता या वर्ग है।
एमोरी

7

इस तरह के इंटरफ़ेस को लागू करने का कोई तरीका नहीं होगा। एक प्रश्न का जवाब जो मैंने दृढ़ता से पेश किया है, यह बताता है कि निजी विधियों के साथ एक इंटरफ़ेस को लागू करने के लिए यह (नियमों को मौलिक रूप से बदलने के बिना) असंभव होगा - यह प्रश्न खुला है कि संरक्षित और पैकेज निजी तरीकों की अनुमति क्यों नहीं है।

class OuterClass
{
     void run ( MyInterface x )
     {
           x . publicMethod ( ) ;  // why not?
           x . protectedMethod ( ) ; // why not?
           x . packagePrivateMethod ( ) ; // why not?
           x . privateMethod ( ) ; // why not?
     }

     interface MyInterface
     {
           public abstract void publicMethod ( ) ; // OK

           protected abstract void protectedMethod ( ) ; // why not?

           abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private

           private void privateMethod ( ) ; // impossible to implement
     }

     class MyImpl implements MyInterface
     {
           public void publicMethod ( ) { } // ok

           protected void protectedMethod ( ) { } // no sweat

           void packagePrivateMethod ( ) { } // no sweat

           private void privateMethod ( ) { } // not happening
     }
}

नीचे दिए गए कोड को वांछित परिणाम प्राप्त करना चाहिए। भले ही सभी विधियाँ सार्वजनिक हों, केवल सार्वजनिक विधि प्रभावी रूप से सार्वजनिक होती है। संरक्षित विधि प्रभावी रूप से संरक्षित है। पैकेजपायरशिपमैथोड प्रभावी रूप से पैकेजपाइप है। PrivateMethod प्रभावी रूप से निजी है।

class WorkAround
{
     void run ( MyPrivateInterface x )
     {
           x . publicMethod ( ) ;  
           x . protectedMethod ( ) ; 
           x . packagePrivateMethod ( ) ; 
           x . privateMethod ( ) ; 
     }

     public interface MyPublicInterface { void publicMethod ( ) ; }

     protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; }

     interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; }

     private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; }
}

6

Javaप्रोग्रामिंग भाषा के अनुसार इसका दायरा private membersसीमित है classजिसमें इसे घोषित किया जाता है और केवल उसी के तरीकों से इसे एक्सेस किया जा सकता है class। लेकिन intefaceएक विधि निकाय नहीं है इसलिए निजी सदस्यों को अंदर घोषित करने का कोई फायदा नहीं है interface


4

जावा 9 में इंटरफ़ेस में निजी तरीकों की अनुमति देता हैडिफ़ॉल्ट तरीकों जावा 8. यह संभव है कि एक से अधिक डिफ़ॉल्ट तरीकों कुछ कोड साझा करना चाहते हैं है में शुरू किए गए थे, फिर यह कोड बाहरी दुनिया के संपर्क में लाने के बिना एक निजी विधि के लिए ले जाया जा सकता है। इस बग को ठीक कर दिया गया है और JDK 9 बिल्ड 54 में शुरू करके , निजी इंटरफ़ेस विधियों के लिए कंपाइलर समर्थन को फिर से जीवित किया गया है।

public interface IData{
   default void processData(int data) {
      validate(data);
      // do some work with it
   }
   default void consumeData(int data) {
      validate(data);
      // do some work with it
   }
   private void validate(int data) {
     // validate data
   }
}

3

यह इसलिए है क्योंकि वे बेकार होंगे।

निजी पद्धति को कॉल करने का कोई तरीका नहीं होगा।

निजी सदस्य कार्यान्वयन विवरण हैं। एक इंटरफ़ेस सार्वजनिक भूमिका के बारे में है जो एक वर्ग ले सकता है।


मैं इस बात से असहमत हूं कि "निजी पद्धति को कॉल करने का कोई तरीका नहीं होगा।" आंतरिक कक्षाओं के साथ, एक रास्ता होगा - stackoverflow.com/a/10169894/348975
एमोरी

जावा 8 के डिफ़ॉल्ट तरीकों पर विचार करें। इंटरफ़ेस I में कई सामान्य कोड के साथ डिफ़ॉल्ट तरीके ए और बी हैं। इसे रीफ़ैक्टर करने के लिए, आप ऐसी विधि C चाहते हैं जिसमें केवल साझा कोड होगा और जिसे A और B द्वारा बुलाया जाएगा। Java 8 में यह एक डिफ़ॉल्ट विधि होगी जो सभी इंटरफ़ेस कार्यान्वयनकर्ताओं के संपर्क में है। Java 9 C में एक निजी विधि हो सकती है जो केवल डिफ़ॉल्ट विधियों में दिखाई देती है I
इवान क्रिलोव

2

निजी क्षेत्र पूरी तरह से बेकार नहीं होंगे क्योंकि अन्य क्षेत्र और आंतरिक वर्ग उन्हें एक्सेस कर सकते हैं।

हालांकि निजी तरीकों को लागू नहीं किया जा सकता था, यहां तक ​​कि नेस्टेड कक्षाओं में भी, उन्हें लगभग बेकार बना दिया। आप उन्हें प्रतिबिंब का उपयोग करके पढ़ सकते हैं, लेकिन यह एक किनारे का मामला है।


यहाँ कब्र खोदने के लिए क्षमा करें :( इस मामले में docs.oracle.com/javase/7/docs/api/java/io/Serializable.html कैसे काम करता है ? क्या लोग इसे लागू नहीं कर सकते और फिर रीडबॉजेक्ट और राइटऑबजेक्ट विधियों को अधिलेखित कर सकते हैं? मुझे यकीन है कि मुझे कुछ याद आ रहा है
पैट्रिकवल्कर

1

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

निजी सदस्य इससे असहमत हैं।


0

किसी वर्ग के सदस्य जिन्हें निजी घोषित किया जाता है, उन्हें उस वर्ग के उपवर्गों द्वारा विरासत में नहीं दिया जाता है। केवल एक वर्ग के सदस्य, जिन्हें संरक्षित या सार्वजनिक घोषित किया जाता है, को एक पैकेज के अलावा अन्य उपवर्गों द्वारा विरासत में दिया जाता है, जिसमें कक्षा को घोषित किया जाता है।

स्रोत

तो आपके पास किसी भी इंटरफ़ेस में काम करने के तरीके नहीं हैं जो उस निजी गैर-अंतर्निहित क्षेत्र के साथ काम कर सकते हैं, फिर इसका अस्तित्व क्यों होना चाहिए?


0

हां, ऐसा नहीं कर सकते। उन सभी के लिए जो इसे क्यों नहीं करना चाहिए:

कल्पना कीजिए कि मेरे पास क्लास ए है, जो इंटरफ़ेस आई क्लास बी का उपयोग करता है, क्लास ए का विस्तार करता है, इसलिए ए में सभी इंटरफ़ेस विधियों को विरासत में मिला है।

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

शायद एक "इनिशियलाइज़ेशन" विधि के लिए, कि मैं एक I इंटरफ़ेस का उपयोग करके सभी वर्गों के लिए चाहता हूं। लेकिन जाहिर है कि मैं एक आरंभीकरण विधि को सार्वजनिक नहीं करना चाहता हूं .... क्योंकि इसका उपयोग केवल एक बार किया जाना चाहिए, या जैसे ही कक्षा आवश्यक हो, केवल इसलिए नहीं कि आप इसे सभी विली-निली का उपयोग करना चाहते हैं।

एकमात्र समाधान वर्कअराउंड है, या केवल इंटरफ़ेस के बिना कक्षाओं में init पद्धति को मजबूर करके।

मुझे इसका कारण समझ में नहीं आता, निश्चित रूप से, लेकिन फिर भी, यह कभी-कभी काम आ सकता है। स्पष्ट रूप से Oracle सहमत हैं क्योंकि वे JDK 9 में निजी इंटरफ़ेस विधियों की अनुमति दे रहे हैं।

मैंने जो कुछ भी किया, उसके लिए, एक साधारण बूलियन वैरिएबल रखा गया था, इस तरह इंटरफ़ेस विधि (जो निजी होनी चाहिए) को एक बार सेट होने के बाद सच (आरंभिक = सत्य) के रूप में चिह्नित किया जा सकता है। फिर जब फिर से विधि कहा जाता है तो कुछ नहीं करता है। इस तरह इंटरफ़ेस विधि को सार्वजनिक रूप से लागू किया जा सकता है, लेकिन चूंकि कंस्ट्रक्टर (मेरी कक्षा का) पहले विधि को कॉल करता है, यह चर को सही करता है, और इसलिए इसे फिर से नहीं बुलाया जा सकता है।

अन्यथा आपको एक अलग वर्कअराउंड की कोशिश करनी होगी यदि आप केवल कक्षा के आंतरिक कामकाज का उपयोग करना चाहते हैं .... शायद एक विधि स्वयं एक ध्वज को सेट और बंद कर देती है क्योंकि यह इसका उपयोग करता है। जब ध्वज गलत होता है, तो विधि कुछ भी नहीं करती है (यह तब होगा जब कोई इसे कक्षा के बाहर से बुलाएगा)। हालाँकि, जब कक्षाएं अपने तरीके से इसे बुलाती हैं, तो वे झंडे को सच में सेट करते हैं, फिर विधि को बुलाते हैं, फिर झंडे को झूठे में सेट करते हैं ??

अंत में मूक। शायद अभी के लिए बेहतर है कि बस निजी वर्ग को कक्षा में ही रखें और इंटरफ़ेस को पूरी तरह से काट दें।

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