2013-01-09 14 views
5

जावा में मित्र अवधारणा को कैसे कार्यान्वित करता है (जैसे सी ++)?जावा में मित्र अवधारणा का कार्यान्वयन

+0

जब भी मैं सी ++ में कोड करता हूं, तब भी मैं 'दोस्त' का उपयोग बहुत कम करता हूं, अगर बिलकुल भी। एक सार्वजनिक इंटरफ़ेस प्रदान करना जो कि सभी द्वारा उपयोग किया जा सकता है, अधिक सुरक्षित है। –

+0

मैंने अपने कोड में जावा में मित्र अवधारणा का उपयोग नहीं किया है। मैं जिज्ञासा के लिए सिर्फ जरूरी था। –

+0

@ कोड-गुरु सार्वजनिक इंटरफ़ेस कैसे मदद करेगा? मैं यहाँ कुछ याद कर रहा हूँ। क्या आप कुछ लिंक देकर कुछ लिंक पोस्ट कर सकते हैं? –

उत्तर

23

जावा में C++ से मित्र कीवर्ड नहीं है। हालांकि, इसका अनुकरण करने का एक तरीका है; एक तरीका है जो वास्तव में बहुत अधिक सटीक नियंत्रण देता है। मान लीजिए कि आप कक्षाएं एक है और बी बी ए में कुछ निजी विधि या क्षेत्र के लिए उपयोग की जरूरत है

public class A { 
    private int privateInt = 31415; 

    public class SomePrivateMethods { 
     public int getSomethingPrivate() { return privateInt; } 
     private SomePrivateMethods() { } // no public constructor 
    } 

    public void giveKeyTo(B other) { 
     other.receiveKey(new SomePrivateMethods()); 
    } 
} 

public class B { 
    private A.SomePrivateMethods key; 

    public void receiveKey(A.SomePrivateMethods key) { 
     this.key = key; 
    } 

    public void usageExample() { 
     A anA = new A(); 

     // int foo = anA.privateInt; // doesn't work, not accessible 

     anA.giveKeyTo(this); 
     int fii = key.getSomethingPrivate(); 
     System.out.println(fii); 
    } 
} 

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

कक्षा बी फिर कुंजी में दिए गए किसी भी तरीके का उपयोग कर सकता है। यह, सी ++ मित्र खोजशब्द की तुलना में स्थापित होने के लिए, अधिक बढ़िया है। कक्षा ए वास्तव में कौन सी विधियों को बेनकाब करने के लिए चुन सकता है।

अब, उपर्युक्त मामले में ए बी के सभी उदाहरणों और बी के उप-वर्गों के उदाहरणों तक पहुंच प्रदान कर रहा है। यदि उत्तरार्द्ध वांछित नहीं है, तो giveKeyTo() विधि आंतरिक रूप से getClass के साथ अन्य प्रकार के सटीक प्रकार की जांच कर सकती है (), और एक अपवाद फेंक दें यदि यह ठीक से बी

+0

बहुत अच्छा। इसे लागू करने का एक बेहतर तरीका संभवतः संभावित सुरक्षा जोखिमों से परहेज करते हुए कक्षा 'बी' को 'अंतिम' घोषित करना होगा। – user991710

1

जावा में आप दोनों (या अधिक) कक्षाओं को एक ही पैकेज में डाल सकते हैं। protected क्वालीफायर के साथ सभी विधियों और फ़ील्ड को सीधे उस पैकेज में सभी कक्षाओं तक पहुंचा जा सकता है।

+0

दरअसल, हालांकि यदि पहले से ही मौजूदा विरासत कोड मौजूद है और रिफैक्टरिंग परेशानी होगी और आप फ़ील्ड और विधियों की दृश्यता को बदलना नहीं चाहते हैं, तो ऐसे दोस्त की नीलामी स्थापित करना एक विकल्प हो सकता है। मैं मानता हूं, यह अत्यधिक पठनीय या अनुशंसित नहीं होगा, लेकिन यह एक त्वरित सुधार के रूप में काम करता है। –

+0

मुझे यह आखिरी खाई, विकल्पों में से सबसे खराब मामला, तकनीकी ऋण के उप-प्रधान स्तरों में आपका स्वागत है, जब यह स्थायी रूप से अस्थायी, या अस्थायी रूप से स्थायी विकल्प बनने की आवश्यकता महसूस करता है। –

+0

लगभग सभी लोग जिन्हें मैं जानता हूं, केवल प्रभावित विधियों को सार्वजनिक रूप से परिभाषित करेंगे, लेकिन आपका दृष्टिकोण दिलचस्प है – AlexWien

-2

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

public class A { 
    private static int privateInt = 31415; 

    public static int getPrivateInt() { 
     if(Throwable().getStackTrace()[1].getClassName().equals(new String("example.java.testing.B"))) 
     { 
     return privateInt; 
     } 
     else 
     { 
     return null; 
     } 
    } 
} 


package example.java.testing; 
public class B { 

public void usageExample() { 
    int foo = A.getPrivateInt; // works only for B 
    System.out.println(foo); 
    } 
} 
3

मान लीजिए A.foo() केवल B द्वारा बुलाया जाना चाहिए। इसे एक टोकन द्वारा व्यवस्थित किया जा सकता है जिसे केवल B द्वारा उत्पन्न किया जा सकता है।

public class B 
{ 
    public static class ToA { private ToA(){} } 
    private static final ToA b2a = new ToA(); 

    void test() 
    { 
     new A().foo(b2a); 
    } 
} 

public class A 
{ 
    public void foo(B.ToA b2a) 
    { 
     if(b2a==null) 
      throw new Error("you ain't B"); 
     // ... 
    } 
} 

केवल B एक गैर-शून्य B.ToA टोकन उत्पन्न कर सकते हैं। A और B दोनों 3 पार्टी को यह टोकन रिसाव नहीं है, तो किसी और कोई भी A.foo()

आह्वान कर सकते हैं A2 दोस्त B करने के लिए बहुत चाहता है, यह एक अलग टोकन प्रकार की जरूरत है। यदि यह वही टोकन प्रकार है, क्योंकि AB से 0 के प्रकार का टोकन मिला है, AB से A2 होने का नाटक कर सकता है।

चेक रनटाइम पर किया जाता है, समय संकलित नहीं करता है, यह सही नहीं है। हालांकि कोई बड़ा सौदा नहीं है, क्योंकि कोई भी तृतीय पक्ष केवल A.foo() को null के साथ बुला सकता है, यह एक निर्दोष गलती नहीं हो सकती है जिसे हम संकलित समय पर जांचना चाहते हैं; यह शायद दुर्भावनापूर्ण है इसलिए हम कॉलर को संकलित समय पर चेतावनी देने की परवाह नहीं करते हैं।

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