जावा में, संरक्षित सदस्यों को उसी पैकेज की कक्षाओं के लिए सुलभ क्यों बनाया गया?


14

आधिकारिक दस्तावेज से ...

संशोधक वर्ग पैकेज उपवर्ग विश्व 
जनता YYYY 
YYYN की रक्षा की 
कोई संशोधक YYNN नहीं 
निजी YNNN 

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

इसके लागू होने के पीछे क्या कारण थे?

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

package some.package;
public class A {
 protected void protectedMethod(){
  // do something
 }
}

package another.package;
public class B extends A{
 public void someMethod(){
  // accessible because B is a subclass of A
  protectedMethod();
 }
} 

package some.package;
public class C {
 public void anotherMethod(){
  // accessible because C is in the same package as A
  protectedMehtod();
 }
}

जवाबों:


4

एक विशिष्ट उपयोग के मामले की तलाश में जहां एक ही पैकेज के भीतर एक उपवर्ग और एक वर्ग दोनों को एक संरक्षित क्षेत्र या विधि का उपयोग करने की आवश्यकता होती है ...

वैसे मेरे लिए, इस तरह का उपयोग मामला विशिष्ट की बजाय सामान्य है, और यह मेरी प्राथमिकताओं से उपजा है:

  1. संभव के रूप में सख्त पहुंच संशोधक के साथ शुरू करें, कमजोर एक (एस) का सहारा लेते हुए केवल बाद में आवश्यक समझा।
  2. यूनिट टेस्ट टेस्ट पैकेज के समान ही होते हैं।

ऊपर से, मैं डिफ़ॉल्ट एक्सेस संशोधक के साथ अपनी वस्तुओं के लिए डिज़ाइन करना शुरू कर सकता हूं (मैं इसके साथ शुरू करूँगा privateलेकिन यह इकाई परीक्षण को जटिल करेगा):

public class Example {
    public static void main(String [] args) {
        new UnitTest().testDoSomething(new Unit1(), new Unit2());
    }

    static class Unit1 {
        void doSomething() {} // default access
    }
    static class Unit2 {
        void doSomething() {} // default access
    }

    static class UnitTest {
        void testDoSomething(Unit1 unit1, Unit2 unit2) {
            unit1.doSomething();
            unit2.doSomething();
        }
    }
}

साइड नोट ऊपर स्निपेट में Unit1, Unit2और UnitTestकर रहे हैं नेस्ट भीतर Exampleप्रस्तुति की सादगी के लिए, लेकिन एक वास्तविक परियोजना में, मैं संभावना अलग फ़ाइलों में (और इन कक्षाओं के लिए होता है UnitTestयहां तक कि एक अलग निर्देशिका में )।

फिर, जब कोई आवश्यकता होती है, तो मैं डिफ़ॉल्ट रूप से अभिगम नियंत्रण को कमजोर कर दूंगा protected:

public class ExampleEvolved {
    public static void main(String [] args) {
        new UnitTest().testDoSomething(new Unit1(), new Unit2());
    }

    static class Unit1 {
        protected void doSomething() {} // made protected
    }
    static class Unit2 {
        protected void doSomething() {} // made protected
    }

    static class UnitTest {
        // ---> no changes needed although UnitTest doesn't subclass
        // ...and, hey, if I'd have to subclass... which one of Unit1, Unit2?
        void testDoSomething(Unit1 unit1, Unit2 unit2) {
            unit1.doSomething();
            unit2.doSomething();
        }
    }
}

आप देखते हैं, मैं ExampleEvolvedएक ही पैकेज से संरक्षित तरीकों के सुलभ होने के कारण यूनिट टेस्ट कोड अपरिवर्तित रख सकता हूं , भले ही एक्सेसिंग ऑब्जेक्ट एक उप-वर्ग न हो

कम परिवर्तन की आवश्यकता => सुरक्षित संशोधन; आखिरकार मैंने केवल एक्सेस मॉडिफ़ायर को बदल दिया और मैंने क्या तरीकों को संशोधित नहीं किया Unit1.doSomething()और Unit2.doSomething()ऐसा किया, इसलिए यूनिट टेस्ट कोड के बिना संशोधनों के साथ जारी रखने की अपेक्षा करना स्वाभाविक है।


5

मैं कहूंगा कि इसके दो भाग हैं:

  1. डिफ़ॉल्ट, "पैकेज", पहुंच विस्तृत मामलों में उपयोगी है, क्योंकि कक्षाएं हमेशा एनकैप्सुलेशन की अच्छी इकाई नहीं होती हैं। विभिन्न समग्र वस्तुएं जहां कुछ वस्तु अन्य वस्तुओं के संग्रह के रूप में कार्य करती है, लेकिन आइटमों को सार्वजनिक रूप से परिवर्तनीय नहीं होना चाहिए, क्योंकि पूरे संग्रह में कुछ अपरिवर्तनीय हैं, इसलिए संग्रह को वस्तुओं तक पहुंच की आवश्यकता है। C ++ में मित्र हैं, जावा में पैकेज एक्सेस है।
  2. अब "पैकेज" एक्सेस स्कोप मूल रूप से "सबक्लास" (संरक्षित) स्कोप से स्वतंत्र है। इसलिए आपको केवल पैकेज, उपवर्ग और पैकेज और उपवर्गों के लिए अतिरिक्त पहुंच विनिर्देशक की आवश्यकता होगी। पैकेज में कक्षाओं के सेट के रूप में "पैकेज" गुंजाइश अधिक प्रतिबंधित है, आमतौर पर निश्चित है जबकि एक उपवर्ग कहीं भी दिखाई दे सकता है। तो चीजों को सरल रखने के लिए, जावा में केवल संरक्षित एक्सेस में पैकेज एक्सेस शामिल है और उप-वर्ग-लेकिन-नहीं-पैकेज के लिए अतिरिक्त निर्दिष्ट नहीं है। हालाँकि आपको लगभग हमेशा ऐसा ही सोचना चाहिए protected

यदि protectedयह केवल उपवर्ग है तो क्या यह सरल नहीं होगा ? ईमानदारी से, एक लंबे समय के लिए, मैं इस धारणा के तहत था कि यह व्यवहार है
jramoyo

@jramoyo: नहीं, क्योंकि आपको अभी भी संयुक्त व्यवहार को किसी भी तरह उपलब्ध कराने की आवश्यकता होगी, जिसका अर्थ एक और स्पेसियर होगा।
Jan Hudec

6
@jramoyo - C # में, protectedकेवल वर्ग और उपवर्ग है, और internalलाइब्रेरी / पैकेज-वाइड है। इसमें वह भी है protected internalजो जावा के समकक्ष है protected
बोबसन

@ बोब्सन - धन्यवाद, C # कार्यान्वयन एक बेहतर विकल्प की तरह लगता है
jramoyo

5

IMHO, यह जावा में एक खराब डिजाइन निर्णय था।

बस अटकलें, लेकिन मुझे लगता है कि वे चाहते थे कि पहुंच का स्तर एक सख्त प्रगति पर हो: निजी - "पैकेज" - संरक्षित - सार्वजनिक। वे एक पदानुक्रम नहीं रखना चाहते थे, जहां कुछ क्षेत्र पैकेज के लिए उपलब्ध होंगे, लेकिन उपवर्ग नहीं, कुछ उपवर्गों के लिए उपलब्ध होंगे, लेकिन पैकेज नहीं और कुछ दोनों।

फिर भी, मेरी विनम्र राय में उन्हें दूसरे तरीके से जाना चाहिए: कहा कि संरक्षित केवल वर्ग और उपवर्गों को दिखाई देता है, और वह पैकेज वर्ग, उपवर्गों और पैकेज को दिखाई देता है।

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

बहुत सारी चीजें हैं जो मैं अपने और अपने बच्चों के बीच निजी रखता हूं और हम पड़ोसियों के साथ साझा नहीं करते हैं। ऐसा बहुत कम है कि मैं अपने और पड़ोसियों के बीच निजी रहूं और अपने बच्चों के साथ साझा न करूं। :-)


0

एक अच्छा उदाहरण जो तुरंत दिमाग में आता है वह है उपयोगिता कक्षाएं जो पैकेज में बहुत अधिक उपयोग की जाती हैं, लेकिन आप सार्वजनिक पहुंच (पर्दे के पीछे-छवि-लोडिंग-डिस्क, हैंडल-निर्माण / विनाश कक्षाएं, आदि) नहीं चाहते हैं ।) के बजाय सब कुछ [जावा के बराबर बनाने का friend access modifier or idiomमें C++हर दूसरे वर्ग सब कुछ की] स्वचालित रूप से उपलब्ध है।


1
उपयोगिता वर्ग उन वर्गों का एक उदाहरण है जो अपने सदस्यों के बजाय आंतरिक रूप से संपूर्ण हैं।
Jan Hudec

0

संरक्षित / पैकेज एक्सेस संशोधक के लिए उपयोग के मामले C ++ में मित्र एक्सेस संशोधक के लिए समान हैं ।

एक उपयोग मामला है जब मेमेंटो पैटर्न को लागू करना है ।

स्मृति चिन्ह वस्तु को पूर्ववत संचालन के लिए एक चेकपॉइंट के रूप में काम करने के लिए, किसी वस्तु की आंतरिक स्थिति तक पहुंचने की आवश्यकता है।

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


1
नहीं, स्मृति वस्तु की जरूरत नहीं है और वस्तु तक कोई पहुंच नहीं होनी चाहिए। यह वह वस्तु है जो खुद को स्मृति चिन्ह में क्रमबद्ध करती है और फिर से चित्रित करती है। और स्मृति चिन्ह केवल एक गूंगा संपत्ति बैग है। न तो सार्वजनिक उपयोग से अधिक दूसरे के पास होना चाहिए।
जन हुदेक

@JanHudec मैंने शाब्दिक रूप से कहा "> एक <- मेमेंटो पैटर्न को प्राप्त करने के संभावित तरीकों में से एक है"
ट्यूलेंस कोर्डोवा

और फिर भी मेमेंटो पैटर्न को प्राप्त करने का एक और संभव तरीका सब कुछ सार्वजनिक करना है। यही है, मैं आपकी बात को देखने में विफल हूं।
थॉमस ईडिंग

-1

समरूपता?

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


1
धन्यवाद, क्या आपके पास एक उदाहरण है? ऐसा लगता है कि "संरक्षित" के बजाय "डिफ़ॉल्ट"
एक्सेसर

-1

जावा के इनकैप्सुलेशन पदानुक्रम को अच्छी तरह से परिभाषित किया गया है:

वर्ग -> पैकेज -> वंशानुक्रम

"संरक्षित" पैकेज डिजाइनरों की तुलना में गोपनीयता का एक कमजोर रूप है जैसा कि जावा डिजाइनरों द्वारा तय किया गया है। पैकेज-डिफॉल्ट आइटम तक पहुंच उन संस्थाओं के सबसेट तक सीमित है जिन्हें संरक्षित वस्तुओं तक पहुंचने की अनुमति है।

यह गणितीय-और कार्यान्वयन की दृष्टि से बहुत मायने रखता है कि आपके पास ऐसी संस्थाओं के सेट हैं जो चीजों को नस्ट होने की अनुमति देते हैं। (आप अपने पैकेज-एक्सेस सेट को अपने संरक्षित-एक्सेस सेट के अंदर घोंसला नहीं बना सकते क्योंकि कक्षाओं को अन्य पैकेजों से विरासत में प्राप्त करने की अनुमति है)।

यह कॉमेडी.example.foo.bar की तुलना में पैकेज में किसी अन्य वर्ग के साथ java.util में कुछ "मैत्री" होने के लिए एक वैचारिक दृष्टिकोण से समझ में आता है। पूर्व मामले में कक्षाएं एक ही लेखक द्वारा लिखे जाने की संभावना है, या कम से कम एक ही संगठन से कोडर।


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