C # C ++ शैली 'मित्र' कीवर्ड क्यों नहीं प्रदान करता है? [बन्द है]


208

सी ++ दोस्त कीवर्ड एक की अनुमति देता है class Aनामित करने के लिए class Bअपने दोस्त के रूप में। यह / के सदस्यों Class Bतक पहुँचने की अनुमति देता है ।privateprotectedclass A

मैंने कभी कुछ नहीं पढ़ा है कि यह C # (और VB.NET) से क्यों छोड़ा गया। इस पहले के StackOverflow प्रश्न के अधिकांश उत्तर यह कहते हुए प्रतीत होते हैं कि यह C ++ का एक उपयोगी हिस्सा है और इसका उपयोग करने के अच्छे कारण हैं। मेरे अनुभव में मुझे सहमत होना पड़ेगा।

एक और सवाल मुझे लगता है कि वास्तव में यह पूछ रहा है कि friendसी # एप्लिकेशन में समान कुछ कैसे किया जाए । हालांकि उत्तर आमतौर पर नेस्टेड कक्षाओं के आसपास घूमते हैं, यह friendकीवर्ड का उपयोग करने के रूप में बहुत सुंदर नहीं लगता है ।

मूल डिज़ाइन पैटर्न बुक अपने उदाहरणों में नियमित रूप से इसका उपयोग करती है।

तो संक्षेप में, friendC # से क्यों गायब है, और C # में इसका अनुकरण करने का "सर्वोत्तम अभ्यास" तरीका (या तरीका) क्या है?

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


5
मुझे लगता है कि संरक्षित आंतरिक एक अच्छा समझौता है ..
गुलज़ार नाज़िम

3
यह बहुत भ्रामक नहीं है? जैसा कि मैंने ऊपर कहा था कि GOF पुस्तक उदाहरणों में इसका अक्सर उपयोग करती है। मेरे लिए यह कोई और अधिक भ्रमित तो आंतरिक है।
ऐश

7
मैं निश्चित रूप से उन परिदृश्यों को देख सकता हूं जहां वे बहुत उपयोगी हो सकते हैं, जैसा कि पहले ही उल्लेख किया गया है यूनिट परीक्षण। लेकिन क्या आप वास्तव में चाहते हैं कि आपके दोस्त आपके प्राइवेट को एक्सेस करें?
danswain

2
इसका उत्तर देना आसान है: C # "आंतरिक" एक्सेस मॉडिफायर के रूप में प्रदान करता है जो एक ही मॉड्यूल / असेंबली में सभी कोड तक पहुंच प्रदान करता है। इससे दोस्त जैसी किसी चीज की जरूरत दूर हो जाती है। जावा में "संरक्षित" कीवर्ड समान पैकेज से समान रूप से राइट एक्सेस का व्यवहार करता है।
बेचें

2
@sellibitze, मैं प्रश्न में आंतरिक के साथ मतभेदों का उल्लेख करता हूं। इंटरनैल के साथ समस्या यह है कि विधानसभा के सभी वर्ग आंतरिक सदस्यों तक पहुंच सकते हैं। इससे अतिक्रमण टूटता है क्योंकि इन वर्गों के लोगों को पहुंच की आवश्यकता नहीं है।
ऐश

जवाबों:


67

प्रोग्रामिंग में दोस्तों का होना अधिक या कम "गंदे" माना जाता है और दुरुपयोग करने में आसान है। यह कक्षाओं के बीच संबंधों को तोड़ता है और एक OO भाषा के कुछ मूलभूत गुणों को कम करता है।

यह कहा जा रहा है, यह एक अच्छी विशेषता है और मैंने इसे C ++ में खुद से बहुत बार उपयोग किया है; और इसे C # में भी इस्तेमाल करना चाहेंगे। लेकिन मैं शर्त लगाता हूं कि C # के "शुद्ध" OOness (C ++ की छद्म ऊँ की तुलना में) MS ने निर्णय लिया कि क्योंकि Java में कोई मित्र कीवर्ड नहीं है, C # या तो नहीं होना चाहिए (सिर्फ मजाक कर रहा है;)

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

EDIT मुझे स्पष्ट करें कि मित्र कीवर्ड OOP को कैसे कम करता है।

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


167
C # 'आंतरिक' वास्तव में C ++ 'मित्र' की तुलना में अधिक एनकैप्सुलेशन को नुकसान पहुंचा रहा है। "दोस्ती" के साथ, मालिक स्पष्ट रूप से जो चाहे उसे अनुमति देता है। "आंतरिक" एक खुले अंत की अवधारणा है।
नागेज़ा ट्रिफ़ुनोविक

21
एंडर्स को उन विशेषताओं के लिए प्रशंसा की जानी चाहिए, जो उन्होंने नहीं छोड़ी थीं।
मेहरदाद अफश्री

21
मैं असहमत हूं कि C # की आंतरिक गतिरोध में बाधा आती है। मेरी राय में विपरीत। आप इसका उपयोग किसी असेंबली के भीतर एक संक्षिप्त पारिस्थितिकी तंत्र बनाने के लिए कर सकते हैं। इस पारिस्थितिक तंत्र के भीतर कई वस्तुएं आंतरिक प्रकारों को साझा कर सकती हैं जो बाकी एप्लिकेशन के संपर्क में नहीं हैं। मैं इन वस्तुओं के लिए यूनिट टेस्ट असेंबली बनाने के लिए "मित्र" असेंबली ट्रिक्स का उपयोग करता हूं।
Quibblesome

26
इसका कोई मतलब नहीं है। friendनिजी सदस्यों तक मनमानी कक्षाओं या कार्यों का उपयोग न होने दें। यह उन विशिष्ट कार्यों या वर्गों को अनुमति देता है जिन्हें मित्र के रूप में चिह्नित किया गया था। निजी सदस्य का वर्ग अभी भी 100% तक पहुंच को नियंत्रित करता है। आप यह भी तर्क दे सकते हैं कि सार्वजनिक सदस्य विधियां। दोनों सुनिश्चित करते हैं कि कक्षा में विशेष रूप से सूचीबद्ध तरीकों को कक्षा के निजी सदस्यों तक पहुंच दी जाए।
जालफ

8
मुझे लगता है कि काफी विपरीत है। यदि किसी असेंबली में 50 वर्ग हैं, यदि उन वर्गों में से 3 किसी उपयोगिता वर्ग का उपयोग करते हैं, तो आज, आपका एकमात्र विकल्प उस उपयोगिता वर्ग को "आंतरिक" के रूप में चिह्नित करना है। ऐसा करने पर, आप इसे केवल 3 वर्गों के लिए उपयोग करने के लिए उपलब्ध नहीं कराते हैं, लेकिन विधानसभा में बाकी कक्षाओं के लिए। क्या होगा अगर आप सब करना चाहते थे तो बेहतर तरीके से पहुंच प्रदान करें जैसे कि प्रश्न में केवल तीन वर्गों की उपयोगिता वर्ग तक पहुंच थी। यह वास्तव में इसे और अधिक वस्तु उन्मुख बनाता है क्योंकि यह एनकैप्सुलेशन में सुधार करता है।
zumalifeguard

104

एक और बात। मित्र का उपयोग करना एनकैप्सुलेशन का उल्लंघन करने के बारे में नहीं है, बल्कि इसके विपरीत इसे लागू करने के बारे में है। एक्सेसर्स + म्यूटेटर्स, ऑपरेटर्स ओवरलोडिंग, पब्लिक इनहेरिटेंस, डाउनकास्टिंग, इत्यादि की तरह , इसका अक्सर दुरुपयोग किया जाता है, लेकिन इसका मतलब यह नहीं है कि कीवर्ड का कोई मतलब नहीं है, या इससे भी बदतर, एक बुरा उद्देश्य है।

देखें कोनराड रूडोल्फ के संदेश अन्य सूत्र में, या यदि आप पसंद को देखने के प्रासंगिक प्रविष्टि सी ++ सवाल जवाब में।


... और FQA में संबंधित प्रविष्टि: yosefk.com/c++fqa/friend.html#fqa-14.2
जोश ली

28
+1 के लिए " मित्र का उपयोग करना एनकैप्सुलेशन का उल्लंघन करने के बारे में नहीं है, लेकिन इसके विपरीत यह इसे लागू करने के बारे में है "
नवाज

2
सिमेंटिक राय का मामला मुझे लगता है; और शायद सवाल में सटीक स्थिति से संबंधित है। कक्षा बनाना friendयह आपके सभी निजी सदस्यों तक पहुँच प्रदान करता है, भले ही आपको केवल उनमें से किसी एक को सेट करने की आवश्यकता हो। एक मजबूत तर्क दिया जा रहा है कि खेतों को दूसरे वर्ग के लिए उपलब्ध कराया जाए जो उन्हें "उल्लंघन का उल्लंघन करने" के रूप में मायने नहीं रखता है। सी ++ में ऐसे स्थान हैं जहां यह आवश्यक है (ऑपरेटरों को ओवरलोड करना), लेकिन एक एन्कैप्सुलेशन ट्रेडऑफ़ है जिसे सावधानी से विचार करने की आवश्यकता है। ऐसा लगता है कि C # डिजाइनरों को लगा कि ट्रेडऑफ़ इसके लायक नहीं है।
ग्रैंडऑपनर

3
एनकैप्सुलेशन आक्रमणकारियों को लागू करने के बारे में है। जब हम एक वर्ग को दूसरे के दोस्त के रूप में परिभाषित करते हैं, तो हम स्पष्ट रूप से कहते हैं कि दो वर्ग पहले वाले के आक्रमणकारियों के प्रबंधन के बारे में दृढ़ता से बंधे हैं। कक्षा की बनी हुई मित्र होने के बावजूद सीधे सभी विशेषताओं को उजागर करने से बेहतर है (सार्वजनिक क्षेत्र के रूप में) या बसने वालों के माध्यम से।
ल्यूक हरमिट

1
बिल्कुल सही। जब आप मित्र का उपयोग करना चाहते हैं, लेकिन आप आंतरिक या सार्वजनिक रूप से उपयोग करने के लिए मजबूर हो सकते हैं, जो कि उन चीजों से अधिक खुला होना चाहिए, जिन्हें नहीं करना चाहिए। खासकर टीम के माहौल में।
Hatchling

50

जानकारी के लिए, .NET में एक और संबंधित-लेकिन-नहीं-काफी-एक ही बात है [InternalsVisibleTo], जो एक असेंबली को एक और असेंबली (जैसे एक यूनिट टेस्ट असेंबली) को नामित करने की अनुमति देता है जो (प्रभावी रूप से) प्रकार / सदस्यों में "आंतरिक" एक्सेस है मूल सभा।


3
अच्छा संकेत, जैसा कि अक्सर दोस्त की तलाश में रहने वाले लोग अधिक आंतरिक 'ज्ञान' रखने की क्षमता के साथ इकाई परीक्षण का तरीका खोजना चाहते हैं।
स्विसकोडर

14

आपको सी # में इंटरफेस का उपयोग करके C ++ के लिए "दोस्त" का उपयोग करने के लिए उसी तरह की चीजों को पूरा करने में सक्षम होना चाहिए। यह आपको स्पष्ट रूप से परिभाषित करने की आवश्यकता है कि कौन से सदस्य दो वर्गों के बीच पारित हो रहे हैं, जो अतिरिक्त काम है, लेकिन कोड को समझने में आसान भी बना सकता है।

अगर किसी के पास "दोस्त" के उचित उपयोग का उदाहरण है जिसे इंटरफेस का उपयोग करके अनुकरण नहीं किया जा सकता है, तो कृपया इसे साझा करें! मैं C ++ और C # के बीच के अंतरों को बेहतर ढंग से समझना चाहूंगा।


अच्छी बात। क्या आपके पास पहले के एसओ प्रश्न (मोनॉक्साइड द्वारा पूछे जाने और ऊपर लिंक किए गए) को देखने का मौका है? मुझे दिलचस्पी है कि सी # में हल करने के लिए सबसे अच्छा कैसे होगा?
ऐश

मुझे यकीन नहीं है कि इसे सी # में कैसे किया जाए, लेकिन मुझे लगता है कि जॉन स्कीट का मोनोऑक्साइड के प्रश्न का उत्तर सही दिशा में है। सी # नेस्टेड क्लासेस की अनुमति देता है। मैंने वास्तव में कोड को हल करने और हल करने की कोशिश नहीं की है, हालांकि। :)
परप्पा

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

3
'फ्रेंड' को रिप्लेस करने के इंटरफ़ेस एप्रोच के साथ समस्या एक इंटरफेस को एक्सपोज़ करने के लिए है, इसका मतलब है कि कोई भी उस इंटरफ़ेस में ऑब्जेक्ट को डाल सकता है और तरीकों तक पहुँच सकता है! आंतरिक, संरक्षित या निजी के लिए इंटरफ़ेस को स्कोप करना या तो काम नहीं करता है जैसे कि काम किया है, तो आप प्रश्न में विधि की गुंजाइश बना सकते हैं! एक शॉपिंग मॉल में एक माँ और बच्चे के बारे में सोचो। दुनिया में जनता सबकी है। आंतरिक मॉल में सिर्फ लोग हैं। निजी सिर्फ मां या बच्चा है। 'मित्र ’केवल माँ और बेटी के बीच की चीज है।
मार्क ए। डोनोहो

1
यहाँ एक है: stackoverflow.com/questions/5921612/… जैसा कि मैं C ++ पृष्ठभूमि से आता हूं, दोस्त की कमी मुझे लगभग रोजाना पागल कर देती है। C # के साथ मेरे कुछ वर्षों में मैंने शाब्दिक रूप से सैकड़ों तरीके सार्वजनिक किए हैं जहां वे मित्र की कमी के कारण निजी और सुरक्षित हो सकते हैं। व्यक्तिगत रूप से मुझे लगता है कि दोस्त सबसे महत्वपूर्ण चीज है जिसे .NET
kaalus

14

साथ friendएक सी ++ डिजाइनर जिसे निजी * सदस्यों के संपर्क में हैं अधिक सटीक नियंत्रण है। लेकिन, वह हर एक निजी सदस्य को बेनकाब करने के लिए मजबूर है।

साथ internalएक सी # डिजाइनर निजी सदस्यों वह उजागर कर रहा है के समूह के ऊपर सटीक नियंत्रण है। जाहिर है, वह सिर्फ एक निजी सदस्य को बेनकाब कर सकता है। लेकिन, यह विधानसभा में सभी वर्गों के सामने होगा।

आमतौर पर, एक डिजाइनर कुछ अन्य वर्गों को चुनने के लिए केवल कुछ निजी तरीकों को उजागर करना चाहता है। उदाहरण के लिए, एक क्लास फैक्ट्री पैटर्न में यह वांछित हो सकता है कि क्लास सी 1 को क्लास फैक्ट्री सीएफ 1 द्वारा ही इंस्टेंट किया जाए। इसलिए वर्ग C1 में एक संरक्षित कंस्ट्रक्टर और एक मित्र वर्ग का कारखाना CF1 हो सकता है।

जैसा कि आप देख सकते हैं, हमारे पास 2 आयाम हैं जिनके साथ एनकैप्सुलेशन भंग हो सकता है। friendइसे एक आयाम के साथ जोड़ता है, internalदूसरे के साथ करता है। इनकैप्सुलेशन कॉन्सेप्ट में कौन सा ज्यादा खराब है? बताना कठिन है। लेकिन यह अच्छा होगा कि दोनों उपलब्ध हों friendऔर internalउपलब्ध हों। इसके अलावा, इन दोनों का एक अच्छा जोड़ 3 प्रकार का कीवर्ड होगा, जिसका उपयोग सदस्य-दर-सदस्य आधार पर किया जाएगा (जैसे internal) और लक्ष्य वर्ग (जैसे friend) को निर्दिष्ट करता है ।

* संक्षिप्तता के लिए मैं "निजी और / या संरक्षित" के बजाय "निजी" का उपयोग करूंगा।

- निक


13

वास्तव में, सी # विशेष शब्दों के बिना शुद्ध ओओपी तरीके से समान व्यवहार प्राप्त करने की संभावना देता है - यह निजी इंटरफेस है।

जहां तक ​​सवाल है कि C # मित्र के समकक्ष क्या है? इस लेख के लिए डुप्लिकेट के रूप में चिह्नित किया गया था और कोई भी वास्तव में अच्छे अहसास का प्रस्ताव नहीं करता है - मैं यहां दोनों प्रश्न पर उत्तर दिखाऊंगा।

मुख्य विचार यहाँ से ले रहा था: एक निजी इंटरफ़ेस क्या है?

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

मुझे लगता है कि वास्तविक व्यवहार में अच्छा उदाहरण पूर्ण राज्य मशीन पैटर्न हो सकता है जहां कुछ नियंत्रक वर्तमान राज्य वस्तु को अद्यतन करते हैं और जब आवश्यक हो तो किसी अन्य राज्य वस्तु पर स्विच करते हैं।

आप ऐसा कर सकते हैं:

  • अपडेट () विधि को सार्वजनिक करने का सबसे आसान और सबसे खराब तरीका है - आशा है कि हर कोई समझ सकता है कि यह बुरा क्यों है।
  • अगला तरीका इसे आंतरिक के रूप में चिह्नित करना है। यह काफी अच्छा है यदि आप अपनी कक्षाओं को किसी अन्य विधानसभा में डालते हैं लेकिन फिर भी उस विधानसभा में प्रत्येक वर्ग प्रत्येक आंतरिक विधि को कॉल कर सकता है।
  • निजी / संरक्षित इंटरफ़ेस का उपयोग करें - और मैंने इस तरह से पालन किया।

Controller.cs

public class Controller
{
    private interface IState
    {
        void Update();
    }

    public class StateBase : IState
    {
        void IState.Update() {  }
    }

    public Controller()
    {
        //it's only way call Update is to cast obj to IState
        IState obj = new StateBase();
        obj.Update();
    }
}

Program.cs

class Program
{
    static void Main(string[] args)
    {
        //it's impossible to write Controller.IState p = new Controller.StateBase();
        //Controller.IState is hidden
        var p = new Controller.StateBase();
        //p.Update(); //is not accessible
    }
}

खैर, विरासत के बारे में क्या?

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

Controller.cs

public class Controller
{
    protected interface IState
    {
        void Update();
    }

    public class StateBase : IState
    {
        void IState.Update() { OnUpdate(); }
        protected virtual void OnUpdate()
        {
            Console.WriteLine("StateBase.OnUpdate()");
        }
    }

    public Controller()
    {
        IState obj = new PlayerIdleState();
        obj.Update();
    }
}

PlayerIdleState.cs

public class PlayerIdleState: Controller.StateBase
{
    protected override void OnUpdate()
    {
        base.OnUpdate();
        Console.WriteLine("PlayerIdleState.OnUpdate()");
    }
}

और अंत में उदाहरण दें कि क्लास कंट्रोलर थ्रो इनहेरिटेंस का परीक्षण कैसे करें: कंट्रोलरटेस्ट.कैंस

class ControllerTest: Controller
{
    public ControllerTest()
    {
        IState testObj = new PlayerIdleState();
        testObj.Update();
    }
}

आशा है कि मैं सभी मामलों को कवर करूंगा और मेरा उत्तर उपयोगी था।


यह एक भयानक उत्तर है जिसे और अधिक सुधार की आवश्यकता है।
KthProg

@ max_cn यह वास्तव में अच्छा समाधान है, लेकिन मैं इस इकाई को परीक्षण के लिए नकली ढांचे के साथ काम करने का एक तरीका देख सकता हूं। कोई सुझाव?
स्टीव लैंड

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

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

@AnthonyMonterrosa, हम सभी बाहरी संसाधनों से अपडेट छिपा रहे हैं, इसलिए आप इसे किसी के साथ साझा क्यों करना चाहते हैं?) सुनिश्चित करें कि आप निजी सदस्यों तक पहुंचने के लिए कुछ सार्वजनिक विधि जोड़ सकते हैं लेकिन यह किसी भी अन्य वर्गों के लिए पिछले दरवाजे की तरह होगा। वैसे भी, यदि आपको परीक्षण प्रयोजनों के लिए इसकी आवश्यकता है - किसी भी परीक्षण मामलों को बनाने के लिए कंट्रोलरटेस्ट क्लास जैसी कुछ बनाने के लिए विरासत का उपयोग करें।
मैक्स_कान

9

यूनिट टेस्ट लिखते समय मित्र बेहद उपयोगी होता है।

जब भी आपकी कक्षा की घोषणा को थोड़ा प्रदूषित करने की लागत आती है, तो यह भी एक संकलक-कार्यान्वित अनुस्मारक है कि वास्तव में कक्षा की आंतरिक स्थिति के बारे में क्या परवाह हो सकती है।

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


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

9

C # "मित्र" कीवर्ड को उसी कारण से याद कर रहा है जो उसके लापता नियतात्मक विनाश का कारण है। कन्वेंशन बदलने से लोग स्मार्ट महसूस करते हैं, जैसे कि उनके नए तरीके किसी और के पुराने तरीकों से बेहतर हैं। यह गर्व की बात है।

यह कहना कि "मित्र वर्ग खराब हैं" अन्य अयोग्य बयानों की तरह ही अदूरदर्शी है जैसे "गोटो का उपयोग न करें" या "लिनक्स विंडोज से बेहतर है"।

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


C # नियतात्मक विनाश को याद नहीं कर रहा है क्योंकि यह कचरा संग्रह से धीमा है। नियतात्मक विनाश निर्मित प्रत्येक वस्तु के लिए समय लेता है, जबकि कचरा संग्रह केवल वर्तमान में जीवित वस्तुओं के लिए समय लेता है। ज्यादातर मामलों में, यह तेज़ है, और सिस्टम में अधिक अल्पकालिक वस्तुएं हैं, अपेक्षाकृत तेज कचरा संग्रह हो जाता है।
एडवर्ड रॉबर्टसन

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

1
... और स्मृति एकमात्र प्रकार का संसाधन नहीं है। लोग अक्सर ऐसा अभिनय करते हैं जैसे यह सच था।
cubuspl42

8

आप C # कीवर्ड "आंतरिक" के साथ C ++ "दोस्त" के करीब पहुंच सकते हैं ।


3
बंद करें, लेकिन काफी नहीं। मुझे लगता है कि यह इस बात पर निर्भर करता है कि आप अपनी असेंबली / कक्षाएं कैसे बनाते हैं, लेकिन मित्र का उपयोग करके दी गई कक्षाओं की संख्या को कम करना अधिक सुरुचिपूर्ण होगा। उपयोगिता / सहायक विधानसभा में एफओआर उदाहरण, सभी वर्गों को आंतरिक सदस्यों तक पहुंच नहीं होनी चाहिए।
ऐश

3
@ एश: आपको इसकी आदत डालनी होगी, लेकिन एक बार जब आप असेंबलियों को अपने अनुप्रयोगों के मूल बिल्डिंग ब्लॉक के रूप में देखते हैं, तो internalयह बहुत अच्छा सौदा होता है और इनकैप्सुलेशन और उपयोगिता के बीच एक उत्कृष्ट व्यापार प्रदान करता है। जावा की डिफ़ॉल्ट पहुँच और भी बेहतर है, हालाँकि।
कोनराड रुडोल्फ

7

यह वास्तव में सी # के साथ एक मुद्दा नहीं है। यह IL में एक मौलिक सीमा है। C # इसके द्वारा सीमित है, जैसा कि कोई भी अन्य .Net भाषा है जो सत्यापन योग्य होना चाहती है। इस सीमा में C ++ / CLI (विशेष खंड 20.5 ) में परिभाषित प्रबंधित कक्षाएं भी शामिल हैं ।

कहा जा रहा है कि मुझे लगता है कि नेल्सन के पास एक अच्छी व्याख्या है कि यह एक बुरी बात क्यों है।


7
-1। friendबुरी बात नहीं है; इसके विपरीत, यह कहीं बेहतर है internal। और नेल्सन का स्पष्टीकरण बुरा और गलत है।
नवाज

4

इस सीमा के बहाने बनाना बंद करो। दोस्त बुरा है, लेकिन आंतरिक अच्छा है? वे एक ही बात कर रहे हैं, केवल वह दोस्त आपको अधिक सटीक नियंत्रण प्रदान करता है कि किसे एक्सेस करने की अनुमति है और कौन नहीं।

यह एनकैप्सुलेशन प्रतिमान को लागू करने के लिए है? तो आपको एक्सेसर के तरीकों को लिखना होगा और अब क्या होगा? आपको इन तरीकों को कॉल करने से सभी को कैसे रोकना चाहिए (कक्षा बी के तरीकों को छोड़कर)? आप नहीं कर सकते, क्योंकि आप "मित्र" के लापता होने के कारण इसे नियंत्रित नहीं कर सकते।

कोई प्रोग्रामिंग भाषा एकदम सही नहीं है। C # उन सर्वश्रेष्ठ भाषाओं में से एक है, जिन्हें मैंने देखा है, लेकिन गुम सुविधाओं के लिए मूर्खतापूर्ण बहाने बनाना किसी की मदद नहीं करता है। C ++ में, मुझे आसान ईवेंट / डेलीगेट सिस्टम, परावर्तन (+ ऑटोमैटिक डी / सीरियलाइज़ेशन) और फ़ॉरइच याद आती है, लेकिन C # I में ऑपरेटर ओवरलोडिंग से चूक जाता है (हाँ, मुझे बताएं कि आपको इसकी आवश्यकता नहीं थी), डिफ़ॉल्ट पैरामीटर, एक const इसे दरकिनार नहीं किया जा सकता, एकाधिक वंशानुक्रम (हाँ, मुझे बताएं कि आपको इसकी आवश्यकता नहीं थी और इंटरफेस पर्याप्त प्रतिस्थापन थे) और स्मृति से एक उदाहरण को हटाने का निर्णय लेने की क्षमता (नहीं, यह बहुत बुरा नहीं है जब तक कि आप एक हैं tinkerer)


C # में आप अधिकांश ऑपरेटरों को ओवरलोड कर सकते हैं। आप असाइनमेंट ऑपरेटरों को अधिभार नहीं दे सकते हैं, लेकिन दूसरी ओर आप उन्हें कम परिचालित करते हुए ओवरराइड ||/ कर सकते हैं &&। डिफ़ॉल्ट पैरामीटर C # 4. में शामिल किए गए
कोडइन्कॉउंस

2

.Net 3 के बाद से InternalsV अदृश्यToAttribute है, लेकिन मुझे संदेह है कि उन्होंने केवल इकाई परीक्षण के उदय के बाद परीक्षण विधानसभाओं को पूरा करने के लिए इसे जोड़ा। मैं इसका उपयोग करने के लिए कई अन्य कारण नहीं देख सकता।

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

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


2

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

हमारे पास क्या है? ("दोस्त" के बारे में कह रहा हूँ "आंतरिक" के बारे में भी कह रहा हूँ)

  • "दोस्त" का उपयोग कर रहा है oo के संबंध में कोड कम शुद्ध?
  • हाँ;

  • "दोस्त" का उपयोग नहीं कर रहा है कोड बेहतर बनाता है?

  • नहीं, हमें अभी भी कक्षाओं के बीच कुछ निजी संबंध बनाने की आवश्यकता है, और हम इसे केवल तभी कर सकते हैं जब हम अपने सुंदर एनकैप्सुलेशन को तोड़ते हैं, इसलिए यह भी अच्छा नहीं है, मैं कह सकता हूं कि "मित्र" का उपयोग करने से भी ज्यादा बुराई क्या है।

मित्र का उपयोग करना कुछ स्थानीय समस्याएं बनाता है, इसका उपयोग नहीं करना कोड-लाइब्रेरी-उपयोगकर्ताओं के लिए समस्याएँ बनाता है।

प्रोग्रामिंग भाषा के लिए सामान्य अच्छा समाधान मैं इस तरह से देखता हूं:

// c++ style
class Foo {
  public_for Bar:
    void addBar(Bar *bar) { }
  public:
  private:
  protected:
};

// c#
class Foo {
    public_for Bar void addBar(Bar bar) { }
}

आपने इस बारे में क्या सोचा? मुझे लगता है कि यह सबसे आम और शुद्ध वस्तु उन्मुख समाधान है। आप अपने द्वारा चुनी गई किसी भी कक्षा तक अपनी पसंद की कोई भी विधि खोल सकते हैं।


मैं एक OOP प्रहरी नहीं हूँ, लेकिन ऐसा लगता है कि यह दोस्त और आंतरिक के खिलाफ हर किसी की पकड़ को हल करता है। लेकिन मैं C # के सिंटैक्स के विस्तार से बचने के लिए एक विशेषता का उपयोग करने का सुझाव दूंगा: [PublicFor Bar] शून्य addBar (बार बार) {} ... ऐसा नहीं है कि मुझे यकीन है कि समझ में आता है; मुझे नहीं पता कि विशेषताएँ कैसे काम करती हैं या क्या वे एक्सेसिबिलिटी के साथ फील कर सकते हैं (वे बहुत सारे "जादुई" सामान करते हैं)।
ग्रेल्ट

2

मैं केवल "कैसे" प्रश्न का उत्तर दूंगा।

यहाँ बहुत सारे उत्तर हैं, हालाँकि मैं उस सुविधा को प्राप्त करने के लिए "डिज़ाइन पैटर्न" का प्रस्ताव करना चाहूंगा। मैं सरल भाषा तंत्र का उपयोग करूंगा, जिसमें शामिल हैं:

  • इंटरफेस
  • नेस्टेड क्लास

उदाहरण के लिए हमारे पास 2 मुख्य कक्षाएं हैं: छात्र और विश्वविद्यालय। छात्र के पास GPA है जिसे केवल विश्वविद्यालय ने एक्सेस करने की अनुमति दी है। यहाँ कोड है:

public interface IStudentFriend
{
    Student Stu { get; set; }
    double GetGPS();
}

public class Student
{
    // this is private member that I expose to friend only
    double GPS { get; set; }
    public string Name { get; set; }

    PrivateData privateData;

    public Student(string name, double gps) => (GPS, Name, privateData) = (gps, name, new PrivateData(this);

    // No one can instantiate this class, but Student
    // Calling it is possible via the IStudentFriend interface
    class PrivateData : IStudentFriend
    {
        public Student Stu { get; set; }

        public PrivateData(Student stu) => Stu = stu;
        public double GetGPS() => Stu.GPS;
    }

    // This is how I "mark" who is Students "friend"
    public void RegisterFriend(University friend) => friend.Register(privateData);
}

public class University
{
    var studentsFriends = new List<IStudentFriend>();

    public void Register(IStudentFriend friendMethod) => studentsFriends.Add(friendMethod);

    public void PrintAllStudentsGPS()
    {
        foreach (var stu in studentsFriends)
            Console.WriteLine($"{stu.Stu.Name}: stu.GetGPS()");
    }
}

public static void Main(string[] args)
{
    var Technion = new University();
    var Alex     = new Student("Alex", 98);
    var Jo       = new Student("Jo", 91);

    Alex.RegisterFriend(Technion);
    Jo.RegisterFriend(Technion);
    Technion.PrintAllStudentsGPS();

    Console.ReadLine();
}

1

मुझे संदेह है कि इसका C # संकलन मॉडल के साथ कुछ करना है - IL को JIT का निर्माण करना जो कि रनटाइम में संकलित करता है। यानी: समान कारण कि C # जेनरिक C ++ जेनरिक के लिए मौलिक रूप से भिन्न हैं।


मुझे लगता है कि संकलक इसे कम से कम एक विधानसभा के भीतर कक्षाओं के बीच आसानी से समर्थन कर सकता है। लक्ष्य वर्ग पर मित्र वर्ग के लिए बस आराम की जाँच का विषय है। बाहरी असेंबली में कक्षाओं के बीच दोस्त को शायद CLR में अधिक मूलभूत परिवर्तनों की आवश्यकता हो सकती है।
ऐश

1

आप इसे निजी रख सकते हैं और कॉल कार्यों के लिए प्रतिबिंब का उपयोग कर सकते हैं। यदि आप इसे किसी निजी फ़ंक्शन का परीक्षण करने के लिए कहते हैं, तो परीक्षण की रूपरेखा ऐसा कर सकती है


जब तक आप सिल्वरलाइट एप्लीकेशन पर काम नहीं कर रहे हैं।
कालस

1

मैं नियमित रूप से दोस्त का उपयोग करता था, और मुझे नहीं लगता कि यह ओओपी का उल्लंघन है या किसी भी डिजाइन दोष का संकेत है। कई जगह हैं जहां यह कम से कम कोड के साथ उचित अंत के लिए सबसे कुशल साधन है।

एक ठोस उदाहरण इंटरफ़ेस असेंबली बनाते समय है जो कुछ अन्य सॉफ़्टवेयर को संचार इंटरफ़ेस प्रदान करता है। आम तौर पर कुछ हैवीवेट वर्ग होते हैं जो प्रोटोकॉल और सहकर्मी विशिष्टताओं की जटिलता को संभालते हैं, और क्लाइंट ऐप और असेंबली के बीच संदेश और सूचनाओं को शामिल करते हुए अपेक्षाकृत सरल कनेक्ट / रीड / राइट / फॉरवर्ड / डिस्कनेक्ट मॉडल प्रदान करते हैं। उन संदेशों / सूचनाओं को कक्षाओं में लपेटा जाना चाहिए। आमतौर पर प्रोटोकॉल सॉफ्टवेयर द्वारा विशेषताओं को हेरफेर करने की आवश्यकता होती है क्योंकि यह उनका निर्माता है, लेकिन बहुत सारे सामान को केवल बाहरी दुनिया के लिए ही पढ़ना पड़ता है।

यह घोषित करने के लिए केवल सादा मूर्खतापूर्ण है कि यह प्रोटोकॉल / "निर्माता" वर्ग के लिए OOP का उल्लंघन है, सभी निर्मित वर्गों तक अंतरंग पहुंच है - निर्माता वर्ग को रास्ते में डेटा के हर बिट को मिलाना पड़ा है। मैंने जो सबसे महत्वपूर्ण पाया है वह यह है कि कोड के सभी बीएस अतिरिक्त लाइनों को "ओओपी के लिए ओओपी की खातिर" मॉडल को आमतौर पर कम से कम किया जाए। अतिरिक्त स्पेगेटी सिर्फ अधिक बग बनाता है।

क्या लोग जानते हैं कि आप विशेषता, संपत्ति और विधि स्तर पर आंतरिक कीवर्ड लागू कर सकते हैं? यह सिर्फ शीर्ष स्तरीय वर्ग घोषणा के लिए नहीं है (हालांकि अधिकांश उदाहरण यह दिखाते हैं।)

यदि आपके पास एक C ++ क्लास है, जो फ्रेंड कीवर्ड का उपयोग करता है, और यह अनुकरण करना चाहता है कि C # क्लास में: 1. C # क्लास को सार्वजनिक घोषित करें। C ++ में सुरक्षित सभी विशेषताओं / गुणों / विधियों को घोषित करें और इस प्रकार दोस्तों के लिए सुलभ हो। C # 3 में आंतरिक। सभी आंतरिक विशेषताओं और गुणों के सार्वजनिक उपयोग के लिए केवल पढ़ने के गुण बनाएँ

मैं मानता हूं कि यह मित्र के समान 100% नहीं है, और इकाई परीक्षण मित्र की तरह कुछ की आवश्यकता का एक बहुत ही मूल्यवान उदाहरण है (जैसा कि प्रोटोकॉल विश्लेषक लॉगिंग कोड है)। हालाँकि आंतरिक उन वर्गों के लिए जोखिम प्रदान करता है जिन्हें आप एक्सपोज़र देना चाहते हैं, और [आंतरिकविशेषज्ञ ()] बाकी को संभालता है - ऐसा लगता है कि यह विशेष रूप से यूनिट टेस्ट के लिए पैदा हुआ था।

जहां तक ​​दोस्त "बेहतर होने के कारण आप आसानी से नियंत्रित कर सकते हैं कि कौन सी कक्षाएं एक्सेस हैं" - क्या बिल्ली में एक ही विधानसभा में संदिग्ध बुराई वर्गों का एक समूह है? विभाजन अपनी विधानसभाओं!


1

दोस्ती को इंटरफेस और कार्यान्वयन को अलग करके अनुकरण किया जा सकता है। विचार यह है: " एक ठोस उदाहरण की आवश्यकता है लेकिन उस उदाहरण के निर्माण की पहुंच को प्रतिबंधित करें "।

उदाहरण के लिए

interface IFriend { }

class Friend : IFriend
{
    public static IFriend New() { return new Friend(); }
    private Friend() { }

    private void CallTheBody() 
    {  
        var body = new Body();
        body.ItsMeYourFriend(this);
    }
}

class Body
{ 
    public void ItsMeYourFriend(Friend onlyAccess) { }
}

इस तथ्य के बावजूद कि ItsMeYourFriend()सार्वजनिक केवल Friendवर्ग ही इसे एक्सेस कर सकता है, क्योंकि कोई और संभवतः Friendकक्षा का एक ठोस उदाहरण प्राप्त नहीं कर सकता है । इसमें निजी कंस्ट्रक्टर है, जबकि फैक्ट्री हैNew() पद्धति एक इंटरफेस देती है।

विवरण के लिए इंटरफेस के लिए कोडिंग के साथ किसी भी कीमत पर मेरे लेख दोस्तों और आंतरिक इंटरफ़ेस सदस्यों को देखें।


अफसोस की बात है कि दोस्ती किसी भी तरह से संभव नहीं है। इस प्रश्न को देखें: stackoverflow.com/questions/5921612/…
kaalus

1

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

मेरे पास एक ASP.NET पेज है जो मेरे अपने आधार पेज को इनहेरिट करता है, जो कि बदले में System.Web.UI.Page को विरासत में देता है। इस पृष्ठ में, मेरे पास कुछ कोड हैं जो एक संरक्षित पद्धति में एप्लिकेशन के लिए अंतिम-उपयोगकर्ता त्रुटि रिपोर्टिंग को संभालता है

ReportError("Uh Oh!");

अब, मेरे पास एक उपयोगकर्ता नियंत्रण है जो पृष्ठ में निहित है। मैं चाहता हूं कि उपयोगकर्ता नियंत्रण पृष्ठ में त्रुटि रिपोर्टिंग विधियों को कॉल करने में सक्षम हो।

MyBasePage bp = Page as MyBasePage;
bp.ReportError("Uh Oh");

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

protected void ReportError(string str) {
    MyBasePage bp = Page as MyBasePage;
    bp.ReportError(str);
}

मेरा मानना ​​है कि भाषा को कम "ओओ" बनाने के बिना मित्र की तरह कुछ उपयोगी और कार्यान्वित किया जा सकता है, जैसे कि विशेषताओं के रूप में, शायद इसलिए कि आपके पास कक्षाएं या विधियां विशिष्ट कक्षाओं या विधियों के दोस्त हो सकते हैं, जिससे डेवलपर को बहुत सुविधा मिल सकती है। विशिष्ट पहुंच। शायद कुछ इस तरह ... (छद्म कोड)

[Friend(B)]
class A {

    AMethod() { }

    [Friend(C)]
    ACMethod() { }
}

class B {
    BMethod() { A.AMethod() }
}

class C {
    CMethod() { A.ACMethod() }
}

मेरे पिछले उदाहरण के मामले में शायद निम्नलिखित की तरह कुछ है (एक शब्दार्थ पर बहस कर सकते हैं, लेकिन मैं सिर्फ इस विचार को प्राप्त करने की कोशिश कर रहा हूं:

class BasePage {

    [Friend(BaseControl.ReportError(string)]
    protected void ReportError(string str) { }
}

class BaseControl {
    protected void ReportError(string str) {
        MyBasePage bp = Page as MyBasePage;
        bp.ReportError(str);
    }
}

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


0

यदि आप C ++ के साथ काम कर रहे हैं और आप अपने स्वयं के मित्र कीवर्ड का उपयोग कर पाते हैं, तो यह एक बहुत ही मजबूत संकेत है, कि आपके पास एक डिज़ाइन मुद्दा है, क्योंकि बिल्ली को एक वर्ग को अन्य वर्ग के निजी सदस्यों तक पहुंचने की आवश्यकता क्यों है ??


मैं सहमत हूँ। मुझे मित्र कीवर्ड की कभी आवश्यकता नहीं है। इसका उपयोग आमतौर पर जटिल रखरखाव मुद्दों को हल करने के लिए किया जाता है।
एडुआर्ड ए।

7
ऑपरेटर ओवरलोडिंग, कोई भी ??
वी आर ऑल मोनिका

3
कितनी बार आपने ऑपरेटर को ओवरलोडिंग के लिए एक अच्छा मामला गंभीरता से पाया?
bashmohandes

8
मैं आपको एक बहुत ही सरल मामला बताता हूँ जो आपकी 'डिज़ाइन समस्या' टिप्पणी को पूरी तरह से समाप्त कर देता है। अभिभावक-बच्चे। एक अभिभावक अपने बच्चों का मालिक होता है। माता-पिता के 'बच्चे' संग्रह में एक बच्चा उस माता-पिता के स्वामित्व में है। चाइल्ड पर पैरेंट प्रॉपर्टी के सेटर को किसी के द्वारा भी व्यवस्थित नहीं किया जाना चाहिए। जब बच्चे को माता-पिता के बच्चों के संग्रह में जोड़ा जाता है, तब ही इसे सौंपा जाना चाहिए। अगर यह सार्वजनिक है, तो कोई भी इसे बदल सकता है। आंतरिक: उस विधानसभा में कोई भी। निजी? कोई नहीं। सेटर को माता-पिता का मित्र बनाना उन मामलों को खत्म करता है और फिर भी आपकी कक्षाओं को अलग रखता है, लेकिन कसकर संबंधित है। हुज़्ज़ाह !!
मार्क ए। डोनोहे

2
ऐसे कई मामले हैं, जैसे कि सबसे बुनियादी प्रबंधक / प्रबंधित पैटर्न। एसओ पर एक और सवाल है और किसी ने भी यह नहीं सोचा कि बिना दोस्त के कैसे किया जाए। सुनिश्चित नहीं है कि लोगों को क्या लगता है कि एक वर्ग "हमेशा पर्याप्त होगा"। कभी-कभी एक से अधिक वर्ग को एक साथ काम करने की आवश्यकता होती है।
कालस

0

bsd

यह कहा गया था कि, दोस्तों को शुद्ध OOness दर्द होता है। जिससे मैं सहमत हूँ।

यह भी कहा गया था कि दोस्तों को एनकैप्सुलेशन में मदद मिलती है, जिसे मैं भी मानता हूं।

मुझे लगता है कि दोस्ती को OO कार्यप्रणाली में जोड़ा जाना चाहिए, लेकिन C ++ में ऐसा नहीं है। मुझे कुछ फ़ील्ड्स / विधियाँ मिलनी चाहिए, जिन्हें मेरा मित्र वर्ग एक्सेस कर सकता है, लेकिन मैं नहीं चाहूंगा कि वे मेरे सभी फ़ील्ड्स / विधियों का उपयोग करें। वास्तविक जीवन में, मैं अपने दोस्तों को अपने व्यक्तिगत रेफ्रिजरेटर का उपयोग करने देता हूं, लेकिन मैं उन्हें अपना बैंक खाता एक्सेस नहीं करने देता।

जैसा कि पालन किया जा सकता है

    class C1
    {
        private void MyMethod(double x, int i)
        {
            // some code
        }
        // the friend class would be able to call myMethod
        public void MyMethod(FriendClass F, double x, int i)
        {
            this.MyMethod(x, i);
        }
        //my friend class wouldn't have access to this method 
        private void MyVeryPrivateMethod(string s)
        {
            // some code
        }
    }
    class FriendClass
    {
        public void SomeMethod()
        {
            C1 c = new C1();
            c.MyMethod(this, 5.5, 3);
        }
    }

यह निश्चित रूप से एक संकलक चेतावनी उत्पन्न करेगा, और अंतर्मुखी को चोट पहुंचाएगा। लेकिन यह काम करेगा।

एक साइड नोट पर, मुझे लगता है कि एक आश्वस्त प्रोग्रामर को निजी सदस्यों तक पहुंच के बिना परीक्षण इकाई करना चाहिए। यह काफी गुंजाइश से बाहर है, लेकिन टीडीडी के बारे में पढ़ने की कोशिश करें। हालाँकि, यदि आप अभी भी ऐसा करना चाहते हैं (दोस्तों की तरह c ++) कुछ ऐसा करने की कोशिश करें

#if UNIT_TESTING
        public
#else
        private
#endif
            double x;

इसलिए आप UNIT_TESTING को परिभाषित किए बिना अपना सारा कोड लिखें और जब आप इकाई परीक्षण करना चाहते हैं तो आप फ़ाइल की पहली पंक्ति में #define UNIT_TESTING जोड़ें (और #if UNIT_TESTING के तहत इकाई परीक्षण करने वाले सभी कोड लिखें)। जिसे सावधानी से संभाला जाना चाहिए।

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


2
वह FriendClass पैरामीटर एक्सेस कंट्रोल के रूप में काम नहीं करता है: आप c.MyMethod((FriendClass) null, 5.5, 3)किसी भी वर्ग से कॉल कर सकते हैं ।
जेसी मैकग्रे ने

0

कुछ आंतरिक वर्गों - "एजेंटों" का उपयोग करके दोस्ती को भी अनुकरण किया जा सकता है। निम्नलिखित उदाहरण पर विचार करें:

public class A // Class that contains private members
{
  private class Accessor : B.BAgent // Implement accessor part of agent.
  {
    private A instance; // A instance for access to non-static members.
    static Accessor() 
    { // Init static accessors.
      B.BAgent.ABuilder = Builder;
      B.BAgent.PrivateStaticAccessor = StaticAccessor;
    }
    // Init non-static accessors.
    internal override void PrivateMethodAccessor() { instance.SomePrivateMethod(); }
    // Agent constructor for non-static members.
    internal Accessor(A instance) { this.instance = instance; }
    private static A Builder() { return new A(); }
    private static void StaticAccessor() { A.PrivateStatic(); }
  }
  public A(B friend) { B.Friendship(new A.Accessor(this)); }
  private A() { } // Private constructor that should be accessed only from B.
  private void SomePrivateMethod() { } // Private method that should be accessible from B.
  private static void PrivateStatic() { } // ... and static private method.
}
public class B
{
  // Agent for accessing A.
  internal abstract class BAgent
  {
    internal static Func<A> ABuilder; // Static members should be accessed only by delegates.
    internal static Action PrivateStaticAccessor;
    internal abstract void PrivateMethodAccessor(); // Non-static members may be accessed by delegates or by overrideable members.
  }
  internal static void Friendship(BAgent agent)
  {
    var a = BAgent.ABuilder(); // Access private constructor.
    BAgent.PrivateStaticAccessor(); // Access private static method.
    agent.PrivateMethodAccessor(); // Access private non-static member.
  }
}

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

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