क्यों एक निजी सदस्य एक स्थिर विधि में सुलभ है?


25

निम्नलिखित छद्म कोड है, मैंने इसे जावा और PHP में आज़माया और दोनों ने काम किया:

class Test { 

    private int a = 5;

    public static function do_test(){
        var t = new Test();
        t.a = 1;
        print t.a // 1
    }

}

Test::do_test();

आप OOP प्रतिमान में ऐसा क्यों कर सकते हैं और इसका क्या उपयोग है?


6
ऐसा क्यों नहीं होगा? जावा में निजी सदस्य उदाहरण के लिए निजी नहीं हैं, बल्कि निजी से स्रोत फ़ाइल तक हैं । दिमाग में आने का पहला उपयोग यह है equalsकि किसी अन्य उदाहरण के निजी क्षेत्रों की जांच करना है। (टिप्पणी के रूप में पोस्टिंग, जैसा कि यह संक्षिप्त है, और इस दृष्टिकोण के
ओओपी

2
ध्यान दें कि स्थिर विधियों में ए नहीं है this, इसलिए उनकी अपनी कक्षा की एकमात्र वस्तुएं जो वे प्राप्त कर सकते हैं वे हैं जो वे स्वयं बनाते हैं (या जो एक पैरामीटर के रूप में पारित हो जाते हैं)। इसलिए यदि आप इसे एनकैप्सुलेशन या सुरक्षा छेद का उल्लंघन मानते हैं, तो ऐसा नहीं है कि यह बहुत बड़ा है, और प्लगिंग नहीं हो सकता है।
किलन फ़ॉथ

4
यकीन नहीं हो रहा है कि यह घट गया। प्रश्न तुच्छ (ईश) हो सकता है, लेकिन ओपी पूछने से पहले दो भाषाओं में व्यवहार का परीक्षण करने की परेशानी से गुजरता है। इस तरह से अधिक प्रयास हम आम तौर पर नए लोगों से देखते हैं।
यानिस

1
@YannisRizos सहमत हैं, और वास्तव में मुझे नहीं लगता कि सवाल तुच्छ है। इसके "कम से कम विशेषाधिकार के सिद्धांत" का पालन करने के निहितार्थ हैं। इसका मतलब है कि ऐसे हेल्पर फ़ंक्शंस जिनके लिए इंस्टेंस के इंटर्ल्स तक पहुंच की ज़रूरत नहीं है, उन्हें एक अलग वर्ग में परिभाषित किया जाना चाहिए , और इसके विपरीत जब इस कन्वेंशन का पालन किया जाता है, तो आपको पता चलेगा कि जब भी एक स्टैटिक विधि एक ही क्लास में मौजूद होती है, तो यह आंतरिक स्थिति तक पहुंच होती है।
डोभाल

1
वास्तव में, जब मैंने अपने सहयोगियों से पूछा तो उन सभी ने कहा कि यह असंभव है। इसलिए मैंने सोचा कि यह तुच्छ नहीं है
बेन

जवाबों:


17

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

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

हालाँकि, जब आप किसी वर्ग के कार्यान्वयन के विवरण को स्थिर तरीकों से या उस वर्ग के अन्य उदाहरणों से भी छुपाना चाहेंगे, तो आप इसका अनुसरण कर सकते हैं निजी वर्ग के डेटा पैटर्न । एक वर्ग के सभी निजी चर को एक निजी आंतरिक वर्ग में रखें और किसी भी गेटर्स को व्यवस्थित करें या उस आंतरिक वर्ग के गेटर्स और बसने वालों को व्यवस्थित करें।

एक अन्य विकल्प वर्ग के लिए एक इंटरफ़ेस को परिभाषित करना है जो वर्ग के सभी सार्वजनिक तरीकों की घोषणा करता है और फिर केवल उस इंटरफ़ेस के तहत कक्षा का संदर्भ देता है जहां भी संभव हो। इंटरफ़ेस-प्रकार के संदर्भ का उपयोग इंटरफ़ेस में घोषित की गई किसी भी चीज़ को सीधे एक्सेस करने के लिए नहीं किया जा सकता है, कोई फर्क नहीं पड़ता जहां (प्रतिबिंब के अलावा, निश्चित रूप से)। जब आप एक ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग भाषा का उपयोग करते हैं, जिसमें कोई इंटरफेस नहीं होता है (जैसे कि C ++, उदाहरण के लिए), तो उन्हें एक एब्सट्रैक्ट बेस-क्लास के साथ सिम्युलेट किया जा सकता है जो वास्तविक वर्ग द्वारा विरासत में मिला है।

interface ITest {
     public int getA();
}

class Test implements ITest { 

    private int a = 5;

    public int getA() { return a; } // implementation of method declared in interface

    public static void main(){
        ITest t = new Test();
        t.a = 1; // syntax error: Interface ITest has no "a"
        System.out.println(t.getA()); // calls Test.getA, visible because ITest declares it
    }

}

क्या आप ऐसी स्थिति के बारे में सोच सकते हैं जब निजी वर्ग डेटा पैटर्न उपयोगी हो? मैं व्यक्तिगत रूप से केवल GUI जैसे कि सेटअप (स्विंग, आदि) या कोडिंग अभ्यासों में स्थिर आंतरिक कक्षाओं में आंतरिक कक्षाओं का उपयोग करता हूं क्योंकि मैं एक से अधिक स्रोत फ़ाइलों का अभ्यास नहीं करना चाहता।
सूचित

1
अन्य उदाहरणों से एक वर्ग के आंतरिक को छुपाने से लाभ के कुछ वर्गों में से एक पर विनिमय के बिना कुछ भी प्राप्त नहीं होता है। एक सरल और अधिक लचीला समाधान सिर्फ एक इंटरफ़ेस का उपयोग करना है।
डोभाल

3

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

किसी भी उदाहरण के निजी सदस्यों का उपयोग करने के लिए किसी भी वर्ग के भीतर किसी भी कोड को अनुमति देने का सबसे बड़ा लाभ यह है कि ऐसे मामले हैं जहां पहुंच का स्तर उचित है, और है private इस तरह से काम करने से उस उद्देश्य के लिए या तो एक अलग पहुँच योग्यता प्राप्त करने की आवश्यकता समाप्त हो जाती है अन्यथा सदस्यों को अधिक मोटे तौर पर उजागर करने के लिए बल कोड अन्यथा आदर्श होगा।

इस तरह की पहुंच को रोकने का एक फायदा (जैसा कि माइक्रोसॉफ्ट कॉमन ऑब्जेक्ट मॉडल (COM) में मामला था) यह है कि यह बाहरी कोड को इंटरफेस के रूप में कक्षाओं का इलाज करने की अनुमति देता है। यदि एक वर्ग ImmutableMatrixमें एक निजी या संरक्षित double[][]बैकिंग फ़ील्ड शामिल है, और यदि कक्षा के भीतर कोड अन्य उदाहरणों के बैकिंग सरणी की जांच करता है, तो यह गैर-सरणी-समर्थित वर्ग (जैसे ) को परिभाषित करना संभव नहीं होगा ZeroMatrix, IdentityMatrixजिसका बाहरी कोड उपयोग कर सकता है ए Immutable2dMatrix, उस क्षेत्र को समर्थन क्षेत्र को शामिल किए बिना। अगर भीतर कुछ Immutable2dMatrixभी अन्य उदाहरणों के निजी सदस्यों का उपयोग नहीं करता है this, तो कक्षा को फिर से नाम देना ImmutableArrayBackedMatrixऔर एक नए अमूर्त ImmutableMatrixवर्ग को परिभाषित करना संभव होगा जो ImmutableArrayBackedMatrixउप-वर्गों के साथ-साथ उपर्युक्त गैर-सरणी-समर्थित कक्षाओं में भी हो सकता है।

ध्यान दें कि जब तक भाषा उस क्षमता का लाभ नहीं लेती और वास्तव में बाहरी उदाहरणों की जांच नहीं करती, तब तक ऐसे रीफैक्टरिंग को भाषा "अनुमति" देने से रोका जा सकता है , जब तक कि ImmutableMatrixअन्य उदाहरणों के लिए बैकिंग ऐरे की जांच thisन की जाए। किसी भाषा के इस तरह के उपयोग को प्रतिबंधित करने का प्राथमिक प्रभाव यह है कि यह कोड लिखने के किसी भी प्रयास में कंपाइलर स्कवॉक को तुरंत कर देगा, जो इस तरह के रिफैक्टरिंग के लिए उत्तरदायी नहीं होगा।


2

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

इसलिए अत्यधिक आश्चर्य न करें कि यह आपको उन चीजों को करने देता है जो कड़ाई से ऑब्जेक्ट-उन्मुख नहीं हैं।

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

यह सी ++ से विरासत में मिला है, जहां यह प्रतिलिपि बनाने और निर्माणकर्ताओं को स्थानांतरित करने के लिए उपयोगी है। यह दो वस्तुओं की तुलना या संयोजन के लिए भी उपयोगी है जहां उनका मूल्य उन सदस्यों पर निर्भर करता है जो एक कुशल तरीके से पारंपरिक रूप से सुलभ नहीं हैं (उदाहरण के लिए, जावा में सरणी के लिए गेट्टर को सरणी को कॉपी करना चाहिए ताकि क्लाइंट कोड इसे बदल नहीं सके, बदल सकता है ऑब्जेक्ट की आंतरिक स्थिति, लेकिन ऑब्जेक्ट समानता की तुलना करने के लिए सरणियों की प्रतिलिपि बनाना कुशल नहीं है)

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