जवाबों:
कुछ कारण जहां आपको निजी कंस्ट्रक्टर की आवश्यकता हो सकती है:
final
कक्षा स्तर पर रखना होगा । निजी कंस्ट्रक्टर को लगाना इस कारण बहुत बेकार है।
final
। यह वही है जो सूर्य ने स्ट्रिंग वर्ग के लिए किया था, और एपीआई का एक उचित हिस्सा जिसे बढ़ाया नहीं जाना चाहिए।
एक निजी कंस्ट्रक्टर प्रदान करके आप कक्षा के उदाहरणों को इस बहुत ही वर्ग के अलावा किसी भी स्थान पर बनाए जाने से रोकते हैं। इस तरह के कंस्ट्रक्टर प्रदान करने के लिए कई उपयोग के मामले हैं।
A. आपकी कक्षा के उदाहरण एक static
विधि में बनाए गए हैं । static
विधि तो के रूप में घोषित किया जाता है public
।
class MyClass()
{
private:
MyClass() { }
public:
static MyClass * CreateInstance() { return new MyClass(); }
};
B. आपकी कक्षा एक सिंगलटन है । इसका अर्थ है, आपकी कक्षा का एक से अधिक उदाहरण कार्यक्रम में मौजूद नहीं है।
class MyClass()
{
private:
MyClass() { }
public:
MyClass & Instance()
{
static MyClass * aGlobalInst = new MyClass();
return *aGlobalInst;
}
};
सी। (केवल आगामी सी ++ 0x मानक पर लागू होता है) आपके पास कई निर्माता हैं। उनमें से कुछ घोषित हैं public
, अन्य private
। कोड के आकार को कम करने के लिए, सार्वजनिक निर्माणकर्ता निजी बिल्डरों को 'कॉल' करते हैं जो बदले में सभी काम करते हैं। आपके public
कंस्ट्रक्टरों को इस तरह से डेलिगेटिंग कंस्ट्रक्टर कहा जाता है :
class MyClass
{
public:
MyClass() : MyClass(2010, 1, 1) { }
private:
MyClass(int theYear, int theMonth, int theDay) { /* do real work */ }
};
डी। आप वस्तु की नकल को सीमित करना चाहते हैं (उदाहरण के लिए, साझा संसाधन का उपयोग करने के कारण):
class MyClass
{
SharedResource * myResource;
private:
MyClass(const MyClass & theOriginal) { }
};
ई। आपकी कक्षा एक उपयोगिता वर्ग है । इसका मतलब है, इसमें केवल static
सदस्य शामिल हैं। इस स्थिति में, प्रोग्राम में कोई ऑब्जेक्ट इंस्टेंस नहीं बनाया जाना चाहिए।
एक "बैक डोर" को छोड़ने के लिए जो किसी अन्य मित्र वर्ग / फ़ंक्शन को उपयोगकर्ता के लिए निषिद्ध तरीके से ऑब्जेक्ट बनाने की अनुमति देता है। एक उदाहरण जो दिमाग में आता है, वह एक कंटेनर होगा जो एक इटेटर (C ++) का निर्माण करेगा:
Iterator Container::begin() { return Iterator(this->beginPtr_); }
// Iterator(pointer_type p) constructor is private,
// and Container is a friend of Iterator.
friend
जहां यह वारंट नहीं है - और ऐसे बहुत सारे मामले हैं जहां यह एक बुरा विचार है। अफसोस की बात है कि संदेश बहुत अच्छी तरह से प्राप्त किया गया है, और कई डेवलपर्स कभी भी भाषा को अच्छी तरह से समझने के लिए कभी नहीं सीखते हैं कि कभी-कभी उपयोग friend
केवल स्वीकार्य नहीं है, लेकिन बेहतर है । आपका उदाहरण सिर्फ इस तरह का मामला था। जानबूझकर मजबूत कपलिंग कोई अपराध नहीं है, यह एक डिजाइन निर्णय है।
हर कोई सिंगलटन की बात पर अड़ा हुआ है, वाह।
अन्य बातें:
यह एक रचनाकार के लिए बहुत उपयोगी हो सकता है जिसमें सामान्य कोड शामिल है; निजी कंस्ट्रक्टरों को 'यह (...);' का उपयोग करके अन्य कंस्ट्रक्टरों द्वारा बुलाया जा सकता है। अंकन। एक निजी (या संरक्षित) कंस्ट्रक्टर में सामान्य आरंभीकरण कोड बनाकर, आप यह भी स्पष्ट रूप से स्पष्ट कर रहे हैं कि इसे केवल निर्माण के दौरान कहा जाता है, जो कि ऐसा नहीं है यदि यह केवल एक विधि है:
public class Point {
public Point() {
this(0,0); // call common constructor
}
private Point(int x,int y) {
m_x = x; m_y = y;
}
};
कुछ उदाहरण हैं जहां आप सार्वजनिक निर्माणकर्ता का उपयोग नहीं करना चाहते हैं; उदाहरण के लिए यदि आप एकल वर्ग चाहते हैं।
यदि आप 3 पार्टियों द्वारा उपयोग की जाने वाली असेंबली लिख रहे हैं, तो कई आंतरिक वर्ग हो सकते हैं जिन्हें आप केवल अपनी असेंबली द्वारा बनाया जाना चाहते हैं और न कि आपके असेंबली के उपयोगकर्ताओं द्वारा इंस्टेंट किया जाए।
यह सुनिश्चित करता है कि आप (निजी कंस्ट्रक्टर के साथ वर्ग) नियंत्रण करते हैं कि कंट्रक्टर को कैसे कहा जाता है।
एक उदाहरण: क्लास पर एक स्थिर फैक्टरी विधि ऑब्जेक्ट्स को वापस कर सकती है क्योंकि फैक्टरी विधि उन्हें आवंटित करने के लिए धोखा देती है (उदाहरण के लिए एक सिंगलटन फैक्ट्री की तरह)।
हमारे पास निजी कंस्ट्रक्टर भी हो सकते हैं, केवल विशिष्ट वर्ग (सुरक्षा कारणों से) द्वारा ऑब्जेक्ट के निर्माण को आगे बढ़ाने के लिए।
C ++ उदाहरण:
class ClientClass;
class SecureClass
{
private:
SecureClass(); // Constructor is private.
friend class ClientClass; // All methods in
//ClientClass have access to private
// & protected methods of SecureClass.
};
class ClientClass
{
public:
ClientClass();
SecureClass* CreateSecureClass()
{
return (new SecureClass()); // we can access
// constructor of
// SecureClass as
// ClientClass is friend
// of SecureClass.
}
};
नोट: नोट: केवल क्लाइंटक्लास (चूंकि यह सिक्योरक्लास का दोस्त है) सिक्योरक्लास के कंस्ट्रक्टर को कॉल कर सकता है।
यहाँ प्राइवेट कंस्ट्रक्टर के कुछ उपयोग दिए गए हैं:
जब आप उपयोगकर्ताओं को इस वर्ग के उदाहरण नहीं बनाना चाहते हैं या इस वर्ग को इनहेरिट करने वाले वर्ग का निर्माण करना चाहते हैं, जैसे java.lang.math
, इस पैकेज में static
सभी फ़ंक्शन हैं, तो सभी कार्यों को एक इंस्टेंस math
बनाए बिना बुलाया जा सकता है , इसलिए निर्माणकर्ता को स्थिर के रूप में घोषित किया जाता है। ।
मैंने आपसे उसी मुद्दे को संबोधित करते हुए एक प्रश्न देखा।
बस अगर आप दूसरों को उदाहरण बनाने की अनुमति नहीं देना चाहते हैं, तो एक सीमित दायरे के भीतर अवरोधक रखें। व्यावहारिक अनुप्रयोग (एक उदाहरण) सिंगलटन पैटर्न है।
आपको नहीं करना चाहिए कंस्ट्रक्टर को निजी बनाना । अवधि। इसे संरक्षित करें, ताकि जरूरत पड़ने पर आप कक्षा का विस्तार कर सकें।
संपादित करें: मैं इसके द्वारा खड़ा हूं, चाहे आप इस पर कितने भी नीचे फेंक दें। आप कोड पर भविष्य के विकास की संभावनाओं को काट रहे हैं। यदि अन्य उपयोगकर्ता या प्रोग्रामर वास्तव में वर्ग का विस्तार करने के लिए दृढ़ हैं, तो वे निर्माणकर्ता को स्रोत या बाइटकोड में संरक्षित करने के लिए बदल देंगे। आपने उनके जीवन को थोड़ा कठिन बनाने के अलावा कुछ भी पूरा नहीं किया होगा। अपने निर्माता की टिप्पणियों में एक चेतावनी शामिल करें, और उस पर छोड़ दें।
यदि यह एक उपयोगिता वर्ग है, तो विस्तार को रोकने के लिए सरल, अधिक सही और अधिक सुरुचिपूर्ण समाधान पूरे वर्ग "स्थिर फाइनल" को चिह्नित करना है। यह केवल कंस्ट्रक्टर प्राइवेट को चिह्नित करने के लिए कोई अच्छा काम नहीं करता है; एक वास्तव में निर्धारित उपयोगकर्ता हमेशा कंस्ट्रक्टर प्राप्त करने के लिए प्रतिबिंब का उपयोग कर सकता है।
protected
कंस्ट्रक्टर का स्टेटिक फ़ैक्टरी विधियों के उपयोग को बाध्य करना है, जो आपको इंस्टेंटेशन या पूल को सीमित करने और महंगे संसाधनों (डीबी कनेक्शन, देशी संसाधनों) का पुन: उपयोग करने की अनुमति देता है।कंस्ट्रक्टर कुछ उद्देश्य के लिए निजी है जैसे कि आपको सिंगलटन लागू करने या किसी कक्षा की वस्तु की संख्या को सीमित करने की आवश्यकता होती है। उदाहरण के लिए सिंगलटन कार्यान्वयन में हमें कंस्ट्रक्टर को निजी बनाना होगा
#include<iostream>
using namespace std;
class singletonClass
{
static int i;
static singletonClass* instance;
public:
static singletonClass* createInstance()
{
if(i==0)
{
instance =new singletonClass;
i=1;
}
return instance;
}
void test()
{
cout<<"successfully created instance";
}
};
int singletonClass::i=0;
singletonClass* singletonClass::instance=NULL;
int main()
{
singletonClass *temp=singletonClass::createInstance();//////return instance!!!
temp->test();
}
फिर से यदि आप 10 तक ऑब्जेक्ट निर्माण को सीमित करना चाहते हैं तो निम्नलिखित का उपयोग करें
#include<iostream>
using namespace std;
class singletonClass
{
static int i;
static singletonClass* instance;
public:
static singletonClass* createInstance()
{
if(i<10)
{
instance =new singletonClass;
i++;
cout<<"created";
}
return instance;
}
};
int singletonClass::i=0;
singletonClass* singletonClass::instance=NULL;
int main()
{
singletonClass *temp=singletonClass::createInstance();//return an instance
singletonClass *temp1=singletonClass::createInstance();///return another instance
}
धन्यवाद
आपके पास एक से अधिक निर्माता हो सकते हैं। यदि आप स्पष्ट रूप से एक प्रदान नहीं करते हैं तो C ++ एक डिफ़ॉल्ट कंस्ट्रक्टर और एक डिफ़ॉल्ट कॉपी कंस्ट्रक्टर प्रदान करता है। मान लीजिए कि आपके पास एक वर्ग है जो केवल कुछ पैरामीटर वाले कंस्ट्रक्टर का उपयोग करके बनाया जा सकता है। हो सकता है कि इसने वैरिएबल को इनिशियलाइज़ किया हो। यदि कोई उपयोगकर्ता उस निर्माता के बिना इस वर्ग का उपयोग करता है, तो वे समस्याओं का कोई अंत नहीं कर सकते हैं। एक अच्छा सामान्य नियम: यदि डिफ़ॉल्ट कार्यान्वयन मान्य नहीं है, तो डिफ़ॉल्ट और कॉपी कंस्ट्रक्टर दोनों को निजी बनाएं और कार्यान्वयन प्रदान न करें:
class C
{
public:
C(int x);
private:
C();
C(const C &);
};
उपयोगकर्ताओं को डिफ़ॉल्ट निर्माता के साथ ऑब्जेक्ट का उपयोग करने से रोकने के लिए कंपाइलर का उपयोग करें जो मान्य नहीं हैं।
प्रभावी जावा से उद्धरण , आपके पास निजी निर्माणकर्ता के साथ उपयोगिता वर्ग रखने के लिए एक वर्ग हो सकता है जो स्थिरांक (स्थिर अंतिम क्षेत्रों के रूप में) को परिभाषित करता है।
( संपादित करें: टिप्पणी के अनुसार यह कुछ ऐसा है जो केवल जावा के साथ लागू हो सकता है, मैं इस बात से अनजान हूँ कि यह निर्माण अन्य OO भाषाओं में लागू है / आवश्यक है (C ++ कहें)
नीचे के रूप में एक उदाहरण:
public class Constants {
private Contants():
public static final int ADDRESS_UNIT = 32;
...
}
EDIT_1 : फिर से, नीचे स्पष्टीकरण जावा में लागू है: (और पुस्तक से संदर्भित, प्रभावी जावा )
उपयोगिता वर्ग की एक तात्कालिकता जैसे नीचे, हालांकि हानिकारक नहीं है, किसी भी उद्देश्य की सेवा नहीं करता है क्योंकि वे तात्कालिक होने के लिए डिज़ाइन नहीं किए गए हैं।
उदाहरण के लिए, मान लें कि क्लास कांस्टेंट के लिए कोई निजी कंस्ट्रक्टर नहीं है। नीचे की तरह एक कोड चंक वैध है, लेकिन कॉन्स्टेंट वर्ग के उपयोगकर्ता के इरादे को बेहतर ढंग से व्यक्त नहीं करता है
unit = (this.length)/new Constants().ADDRESS_UNIT;
जैसे कोड के विपरीत
unit = (this.length)/Constants.ADDRESS_UNIT;
इसके अलावा, मुझे लगता है कि एक निजी कंस्ट्रक्टर कॉन्स्टेंट्स (कहना) वर्ग के डिजाइनर के इरादे को बेहतर बताता है।
यदि कोई कंस्ट्रक्टर प्रदान नहीं किया जाता है, तो जावा एक डिफ़ॉल्ट पैरामीटर रहित सार्वजनिक कंस्ट्रक्टर प्रदान करता है, और यदि आपका इरादा तात्कालिकता को रोकने का है तो एक निजी कंस्ट्रक्टर की आवश्यकता है।
एक शीर्ष स्तर के स्थिर वर्ग को चिह्नित नहीं कर सकता है और यहां तक कि एक अंतिम वर्ग को तत्काल किया जा सकता है।
उपयोगिता वर्ग में निजी निर्माणकर्ता हो सकते हैं। वर्गों के उपयोगकर्ताओं को इन वर्गों को तुरंत करने में सक्षम नहीं होना चाहिए:
public final class UtilityClass {
private UtilityClass() {}
public static utilityMethod1() {
...
}
}
एक महत्वपूर्ण उपयोग सिंगलटन वर्ग में है
class Person
{
private Person()
{
//Its private, Hense cannot be Instantiated
}
public static Person GetInstance()
{
//return new instance of Person
// In here I will be able to access private constructor
}
};
यह भी उपयुक्त है, यदि आपकी कक्षा में केवल स्थिर विधियाँ हैं। अर्थात किसी को भी आपकी कक्षा को तुरंत करने की आवश्यकता नहीं है
यह वास्तव में एक स्पष्ट कारण है: आप एक वस्तु का निर्माण करना चाहते हैं, लेकिन निर्माणकर्ता के भीतर इसे (इंटरफ़ेस की अवधि में) करना व्यावहारिक नहीं है।
Factory
उदाहरण काफी स्पष्ट है, मुझे का प्रदर्शन करते हैं Named Constructor
मुहावरा।
कहें कि मेरे पास एक वर्ग है Complex
जो एक जटिल संख्या का प्रतिनिधित्व कर सकता है।
class Complex { public: Complex(double,double); .... };
सवाल यह है: क्या निर्माता वास्तविक और काल्पनिक भागों की अपेक्षा करता है, या क्या यह आदर्श और कोण (ध्रुवीय निर्देशांक) की अपेक्षा करता है?
मैं इंटरफ़ेस को आसान बनाने के लिए बदल सकता हूं:
class Complex
{
public:
static Complex Regular(double, double = 0.0f);
static Complex Polar(double, double = 0.0f);
private:
Complex(double, double);
}; // class Complex
इसे Named Constructor
मुहावरा कहा जाता है : वर्ग केवल खरोंच से बनाया जा सकता है यह स्पष्ट रूप से कहा जाता है कि हम किस निर्माणकर्ता का उपयोग करना चाहते हैं।
यह कई निर्माण विधियों का एक विशेष मामला है। डिजाइन पैटर्न का निर्माण वस्तु के लिए तरीके का एक अच्छी संख्या प्रदान करते हैं: Builder
, Factory
, Abstract Factory
, ... और एक निजी निर्माता यह सुनिश्चित करेंगे कि उपयोगकर्ता ठीक से विवश है।
बेहतर उपयोग के अलावा…
विधि ऑब्जेक्ट पैटर्न को लागू करने के लिए , जिसे मैं संक्षेप में प्रस्तुत करूंगा:
"निजी निर्माता, सार्वजनिक स्थैतिक विधि"
"कार्यान्वयन के लिए उद्देश्य, इंटरफ़ेस के लिए कार्य"
यदि आप किसी ऑब्जेक्ट का उपयोग करके फ़ंक्शन को कार्यान्वित करना चाहते हैं, और ऑब्जेक्ट एक-ऑफ संगणना (एक विधि कॉल द्वारा) करने से बाहर उपयोगी नहीं है, तो आपके पास एक थ्रॉवे ऑब्जेक्ट है । आप इस सामान्य विरोधी प्रतिमान को रोकते हुए वस्तु निर्माण और विधि कॉल को एक स्थिर विधि में संलग्न कर सकते हैं:
z = new A(x,y).call();
... इसे (नाम स्थान) फ़ंक्शन कॉल के साथ प्रतिस्थापित करना:
z = A.f(x,y);
कॉल करने वाले को यह जानने या देखभाल करने की आवश्यकता नहीं है कि आप आंतरिक रूप से एक ऑब्जेक्ट का उपयोग कर रहे हैं, एक क्लीनर इंटरफ़ेस उपज है, और ऑब्जेक्ट के चारों ओर लटका हुआ ऑब्जेक्ट या गलत उपयोग से कचरा को रोकते हैं।
उदाहरण के लिए, आप तरीकों के पार एक अभिकलन को तोड़ने के लिए चाहते हैं, तो foo
, bar
है, और zork
में और कार्यों से बाहर है, तो आप इसे लागू कर सकता है के रूप में इस प्रकार कई मान पास करने के बिना शेयर राज्य के लिए उदाहरण के लिए,:
class A {
public static Z f(x, y) {
A a = new A(x, y);
a.foo();
a.bar();
return a.zork();
}
private A(X x, Y y) { /* ... */ };
}
यह विधि ऑब्जेक्ट पैटर्न स्मॉलटाकल बेस्ट प्रैक्टिस पैटर्न , केंट बेक, पेज 34-37 में दी गई है, जहां यह एक रिफैक्टिंग पैटर्न का अंतिम चरण है, जो समाप्त होता है:
- मूल विधि के मापदंडों और रिसीवर के साथ निर्मित, नए वर्ग का एक उदाहरण बनाने वाले मूल विधि को बदलें, और "कंपोज" को आमंत्रित करें।
यह यहां अन्य उदाहरणों से काफी भिन्न है: वर्ग तात्कालिक है (एक उपयोगिता वर्ग के विपरीत), लेकिन उदाहरण निजी हैं (कारखाने के तरीकों के विपरीत, सिंगललेट्स आदि सहित), और स्टैक पर रह सकते हैं, क्योंकि वे कभी बच नहीं जाते हैं।
यह पैटर्न बोतलों-अप ओओपी में बहुत उपयोगी है, जहां वस्तुओं का उपयोग निम्न-स्तरीय कार्यान्वयन को सरल बनाने के लिए किया जाता है, लेकिन जरूरी नहीं कि बाहरी रूप से उजागर हो, और टॉप-डाउन ओओपी के साथ विरोधाभास जो अक्सर प्रस्तुत किया जाता है और उच्च-स्तरीय इंटरफेस के साथ शुरू होता है।
कभी-कभी उपयोगी होता है यदि आप नियंत्रित करना चाहते हैं कि किसी वस्तु के कैसे और कब (और कितने) उदाहरण बनते हैं।
दूसरों के बीच, पैटर्न में उपयोग किया जाता है:
Singleton pattern
Builder pattern
निजी निर्माणकर्ताओं के उपयोग से डोमेन-संचालित डिज़ाइन के सामने पठनीयता / स्थिरता को बढ़ाया जा सकता है। "Microsoft .NET - एंटरप्राइज़, द्वितीय संस्करण के लिए आर्किटेकिंग एप्लिकेशन" से:
var request = new OrderRequest(1234);
उद्धरण, "यहां दो समस्याएं हैं। सबसे पहले, जब कोड को देखते हैं, तो शायद ही कोई अनुमान लगा सकता है कि क्या चल रहा है। ऑर्डरअर्सपेस्ट का एक उदाहरण बनाया जा रहा है, लेकिन क्यों और किस डेटा का उपयोग किया जा रहा है? 1234 क्या है? यह दूसरी समस्या की ओर जाता है: आप बंधे हुए संदर्भ की सर्वव्यापी भाषा का उल्लंघन कर रहे हैं। भाषा शायद कुछ इस तरह से कहती है: एक ग्राहक एक आदेश अनुरोध जारी कर सकता है और एक खरीद आईडी निर्दिष्ट करने की अनुमति दी जाती है। यदि यह मामला है, तो यहां एक नया आदेश प्राप्त करने का बेहतर तरीका है। : "
var request = OrderRequest.CreateForCustomer(1234);
कहाँ पे
private OrderRequest() { ... }
public OrderRequest CreateForCustomer (int customerId)
{
var request = new OrderRequest();
...
return request;
}
मैं हर एक वर्ग के लिए इसकी वकालत नहीं कर रहा हूं, लेकिन उपरोक्त डीडीडी परिदृश्य के लिए मुझे लगता है कि यह एक नई वस्तु के प्रत्यक्ष निर्माण को रोकने के लिए बिल्कुल सही समझ में आता है।