2013-01-14 18 views
18

मुझे दो उदाहरणों की आवश्यकता है जिनके पास एक-दूसरे के निजी अधिकार हैं। मैं स्वाभाविक रूप से एक साथी वस्तु के बारे में सोचता हूं जो कि इसके एक साथी वर्ग के एकमात्र उदाहरण तक पहुंच प्रदान करता है। कक्षा स्वयं ही मैंने निजी बना दी है, इसलिए उपयोगकर्ता new का उपयोग करके उदाहरण नहीं बना सकते हैं।साथी वर्ग एक निजी वर्ग के लिए: यह मान्य क्यों नहीं है?

object A { 
    def apply = dual 
    lazy val dual = new A 
} 

private class A { 
    //some irrelevant logic... 
} 

यह कोड संकलित नहीं करता है। मुझे मिलता है: कक्षा ए टाइप ए त्रुटि के हिस्से के रूप में अपने परिभाषित दायरे से बच निकलता है, जिसे मैं वास्तव में समझ में नहीं आता। मेरा वर्तमान कामकाज कक्षा के प्रत्येक विधि घोषणा के साथ एक विशेषता को परिभाषित करना था और class A उस विशेषता का विस्तार करना था, जबकि दोहरी विशेषता प्रकार का है, और class A प्रकार नहीं है।

सैद्धांतिक समस्या क्या है मैं यहां याद कर रहा हूं? यह क्यों मना है?

+8

हेहेहे एक दूसरे के लिए पहुंच –

+2

@ AK4749 अच्छी तरह से निजी है, उसके बाद उसके साथी के बारे में हम बात कर रहे हैं। ऐसा नहीं है कि वर्ग सिर्फ _anyone_ को अपने निजी लोगों तक पहुंचने की अनुमति दे रहा है ... हालांकि _reflection _... –

उत्तर

29

पाओलो का समाधान अच्छा है (+1), लेकिन उसने त्रुटि संदेश की व्याख्या नहीं की, इसलिए मुझे इसे आज़माएं। समस्या इस तथ्य से उत्पन्न होती है कि प्रत्येक विधि को वापसी प्रकार की आवश्यकता होती है। apply और dual की आपकी मूल परिभाषा class A की एक वस्तु लौटा दी, इस प्रकार दोनों का अंतर्निहित वापसी प्रकार A था। इसका तात्पर्य है कि A ग्राहकों के लिए दृश्यमान होना चाहिए - वे फ़ंक्शन को कैसे कॉल कर सकते हैं या val तक पहुंच सकते हैं? इसके अलावा, दोनों - और उनके मूल वस्तु भी - सार्वजनिक हैं, वे विश्व स्तर पर दिखाई दे रहे हैं। हालांकि, आपने A private घोषित किया जिसका अर्थ है कि इसे अपने पैकेज के बाहर दिखाई नहीं देना चाहिए। तो एक संघर्ष है जिसे संकलक द्वारा हल नहीं किया जा सकता है।

सामान्य नियम यह है कि सभी पैरामीटर और वापसी प्रकार/सदस्यों के पास दृश्यता सदस्य के रूप में दृश्यता के समान दायरे (कम से कम) होना चाहिए। इस प्रकार इस समस्या को हल करने का एक छोटा तरीका apply और dual से private की दृश्यता को कम करना होगा। यह कंपाइलर को संतुष्ट करेगा, लेकिन आप नहीं :-)

आपका समाधान स्थिर रिटर्न प्रकार को public विशेषता में बदलकर समस्या के आसपास आता है, इस प्रकार सदस्यों के संदर्भ में समान दृश्यता होती है। लौटाई गई वस्तु का गतिशील प्रकार अभी भी class A है, हालांकि, यह ग्राहकों को दिखाई नहीं दे सकता है। यह सिद्धांत "program to interfaces, not implementations" का एक उत्कृष्ट उदाहरण है।

ध्यान दें कि सीमा तक इस सिद्धांत लागू करने के लिए, एक object A के private भीतरी वर्ग में class A बदल सकता है, इस प्रकार एक ही पैकेज में अन्य वर्गों के लिए यह innaccessible बनाने:

trait A { 
    //... 
} 

object A { 
    def apply: A = dual 
    lazy val dual: A = new AImpl 

    private class AImpl extends A { 
     //some irrelevant logic... 
    } 

} 

* करने के लिए पंडिताऊ हो, संलग्नित क्लास/वस्तु यहाँ की तरह अपने सदस्यों की दृश्यता कम कर सकते हैं,:

private class Holder { 
    def member = new Hidden 
} 

private class Hidden 

जहां memberpublic है लेकिन इसकी संलग्न कक्षा private है, जो प्रभावी रूप से बाहरी सदस्यों से अपने सदस्यों को छुपा रही है। तो संकलक यहां कोई शिकायत नहीं करता है।

+0

यह वास्तव में एक बहुत अच्छा जवाब –

+0

है! एक बहुत अच्छा जवाब ..! धन्यवाद! –

23

मुझे लगता है कि आप एक निजी वर्ग नहीं चाहते हैं, लेकिन एक निजी निर्माता के साथ एक कक्षा।

class A private() 
object A { 
    def apply = dual 
    lazy val dual = new A 
} 

अब अपनी कक्षा के बाहर कोड को "दृश्यमान" है, लेकिन केवल अपने साथी वस्तु इसके बारे में उदाहरण बना सकते हैं।

+0

धन्यवाद! मुझे मूर्खतापूर्ण ... कभी-कभी, सबसे परेशान समस्याएं, वास्तव में मूर्खतापूर्ण और सरल होती हैं। –

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