ऑपरेटर ओवरलोडिंग के बारे में शिकायत करने वाले बहुत सारे पद हैं।
मुझे लगा कि मुझे "ऑपरेटर ओवरलोडिंग" अवधारणाओं को स्पष्ट करना होगा, इस अवधारणा पर एक वैकल्पिक दृष्टिकोण प्रस्तुत करना होगा।
कोड को बाधित कर रहा है?
यह तर्क एक पतन है।
सभी भाषाओं में विरोध संभव है ...
यह कार्य / विधियों के माध्यम से C या Java में कोड को आबंटित करना उतना ही आसान है जितना कि ऑपरेटर ओवरलोड के माध्यम से C ++ में है:
// C++
T operator + (const T & a, const T & b) // add ?
{
T c ;
c.value = a.value - b.value ; // subtract !!!
return c ;
}
// Java
static T add (T a, T b) // add ?
{
T c = new T() ;
c.value = a.value - b.value ; // subtract !!!
return c ;
}
/* C */
T add (T a, T b) /* add ? */
{
T c ;
c.value = a.value - b.value ; /* subtract !!! */
return c ;
}
... जावा के मानक इंटरफेस में भी
एक अन्य उदाहरण के लिए, आइए जावा में Cloneable
इंटरफेस देखें :
आप इस इंटरफ़ेस को लागू करने वाले ऑब्जेक्ट को क्लोन करने वाले हैं। लेकिन आप झूठ बोल सकते थे। और एक अलग वस्तु बनाएं। वास्तव में, यह इंटरफ़ेस इतना कमजोर है कि आप किसी अन्य प्रकार की वस्तु को पूरी तरह से वापस कर सकते हैं, बस इसके मज़े के लिए:
class MySincereHandShake implements Cloneable
{
public Object clone()
{
return new MyVengefulKickInYourHead() ;
}
}
के रूप में Cloneable
इंटरफ़ेस का दुरुपयोग किया जा सकता है / बाधित किया जा सकता है, क्या इसे उसी आधार पर प्रतिबंधित किया जाना चाहिए C ++ ऑपरेटर ओवरलोडिंग माना जाता है?
हम toString()
एक MyComplexNumber
वर्ग की विधि को ओवरलोड कर सकते हैं ताकि यह दिन के कड़े घंटे को वापस कर सके। क्या toString()
ओवरलोडिंग पर भी रोक लगनी चाहिए? हम तोड़फोड़ कर सकते हैं MyComplexNumber.equals
कि यह एक यादृच्छिक मूल्य लौटाए, ऑपरेंड को संशोधित करें ... आदि आदि।
जावा में, सी ++ की तरह, या जो भी भाषा में, प्रोग्रामर को कोड लिखते समय न्यूनतम शब्दार्थ का सम्मान करना चाहिए। इसका अर्थ है एक add
फ़ंक्शन को लागू करना , जो जोड़ता है, और Cloneable
कार्यान्वयन विधि जो क्लोन, और ए++
वेतन वृद्धि की तुलना में ऑपरेटर है।
वैसे भी क्या बात है?
अब जब हम जानते हैं कि कोड को प्राचीन जावा विधियों के माध्यम से भी तोड़फोड़ किया जा सकता है, तो हम खुद को C ++ में ऑपरेटर ओवरलोडिंग के वास्तविक उपयोग के बारे में पूछ सकते हैं?
स्पष्ट और प्राकृतिक संकेतन: तरीके बनाम ऑपरेटर ओवरलोडिंग?
हम नीचे की तुलना करेंगे, विभिन्न मामलों के लिए, जावा और सी ++ में "समान" कोड, जिससे अंदाजा लगाया जा सके कि किस तरह की कोडिंग शैली स्पष्ट है।
प्राकृतिक तुलना:
// C++ comparison for built-ins and user-defined types
bool isEqual = A == B ;
bool isNotEqual = A != B ;
bool isLesser = A < B ;
bool isLesserOrEqual = A <= B ;
// Java comparison for user-defined types
boolean isEqual = A.equals(B) ;
boolean isNotEqual = ! A.equals(B) ;
boolean isLesser = A.comparesTo(B) < 0 ;
boolean isLesserOrEqual = A.comparesTo(B) <= 0 ;
कृपया ध्यान दें कि A और B C ++ में किसी भी प्रकार के हो सकते हैं, जब तक कि ऑपरेटर ओवरलोड प्रदान नहीं किए जाते हैं। जावा में, जब ए और बी आदिम नहीं होते हैं, तो कोड बहुत भ्रामक हो सकता है, यहां तक कि आदिम-जैसी वस्तुओं (बिगइन्टेगर, आदि) के लिए भी ...
प्राकृतिक सरणी / कंटेनर एक्सेसर्स और सबस्क्रिप्टिंग:
// C++ container accessors, more natural
value = myArray[25] ; // subscript operator
value = myVector[25] ; // subscript operator
value = myString[25] ; // subscript operator
value = myMap["25"] ; // subscript operator
myArray[25] = value ; // subscript operator
myVector[25] = value ; // subscript operator
myString[25] = value ; // subscript operator
myMap["25"] = value ; // subscript operator
// Java container accessors, each one has its special notation
value = myArray[25] ; // subscript operator
value = myVector.get(25) ; // method get
value = myString.charAt(25) ; // method charAt
value = myMap.get("25") ; // method get
myArray[25] = value ; // subscript operator
myVector.set(25, value) ; // method set
myMap.put("25", value) ; // method put
जावा में, हम देखते हैं कि प्रत्येक कंटेनर को एक ही काम करने के लिए (एक सूचकांक या पहचानकर्ता के माध्यम से अपनी सामग्री तक पहुंच), हमारे पास इसे करने का एक अलग तरीका है, जो भ्रामक है।
सी ++ में, प्रत्येक कंटेनर अपनी सामग्री तक पहुंचने के लिए उसी तरह का उपयोग करता है, ऑपरेटर ओवरलोडिंग के लिए धन्यवाद।
प्राकृतिक उन्नत प्रकार हेरफेर
Matrix
" जावा मैट्रिक्स ऑब्जेक्ट " और " C ++ मैट्रिक्स ऑब्जेक्ट " के लिए Google पर पाए गए पहले लिंक का उपयोग करते हुए नीचे दिए गए उदाहरण एक वस्तु का उपयोग करते हैं :
// C++ YMatrix matrix implementation on CodeProject
// http://www.codeproject.com/KB/architecture/ymatrix.aspx
// A, B, C, D, E, F are Matrix objects;
E = A * (B / 2) ;
E += (A - B) * (C + D) ;
F = E ; // deep copy of the matrix
// Java JAMA matrix implementation (seriously...)
// http://math.nist.gov/javanumerics/jama/doc/
// A, B, C, D, E, F are Matrix objects;
E = A.times(B.times(0.5)) ;
E.plusEquals(A.minus(B).times(C.plus(D))) ;
F = E.copy() ; // deep copy of the matrix
और यह मैट्रिसेस तक सीमित नहीं है। BigInteger
औरBigDecimal
जावा के कक्षाएं, एक ही भ्रामक शब्दाडंबर से ग्रस्त हैं जबकि सी में उनके समकक्ष ++ के रूप में कर रहे हैं में निर्मित प्रकार के रूप में स्पष्ट है।
प्राकृतिक पुनरावृत्तियों:
// C++ Random Access iterators
++it ; // move to the next item
--it ; // move to the previous item
it += 5 ; // move to the next 5th item (random access)
value = *it ; // gets the value of the current item
*it = 3.1415 ; // sets the value 3.1415 to the current item
(*it).foo() ; // call method foo() of the current item
// Java ListIterator<E> "bi-directional" iterators
value = it.next() ; // move to the next item & return the value
value = it.previous() ; // move to the previous item & return the value
it.set(3.1415) ; // sets the value 3.1415 to the current item
प्राकृतिक फंक्शनलर्स:
// C++ Functors
myFunctorObject("Hello World", 42) ;
// Java Functors ???
myFunctorObject.execute("Hello World", 42) ;
पाठ संयोजन:
// C++ stream handling (with the << operator)
stringStream << "Hello " << 25 << " World" ;
fileStream << "Hello " << 25 << " World" ;
outputStream << "Hello " << 25 << " World" ;
networkStream << "Hello " << 25 << " World" ;
anythingThatOverloadsShiftOperator << "Hello " << 25 << " World" ;
// Java concatenation
myStringBuffer.append("Hello ").append(25).append(" World") ;
ठीक है, जावा में आप उपयोग कर सकते हैं MyString = "Hello " + 25 + " World" ;
... लेकिन, एक सेकंड रुको: यह ऑपरेटर ओवरलोडिंग है, है ना? क्या यह धोखा नहीं है ???
:-D
सामान्य कोड?
समान जेनेरिक कोड संशोधित ऑपरेंड्स बिल्ट-इन / प्राइमेटिव्स (जिनका जावा में कोई इंटरफेस नहीं है), स्टैंडर्ड ऑब्जेक्ट्स (जिसमें सही इंटरफ़ेस नहीं हो सकता) और यूज़र-डिफ़ाइंड ऑब्जेक्ट्स दोनों के लिए उपयोग योग्य होना चाहिए।
उदाहरण के लिए, मनमाने प्रकार के दो मूल्यों के औसत मूल्य की गणना:
// C++ primitive/advanced types
template<typename T>
T getAverage(const T & p_lhs, const T & p_rhs)
{
return (p_lhs + p_rhs) / 2 ;
}
int intValue = getAverage(25, 42) ;
double doubleValue = getAverage(25.25, 42.42) ;
complex complexValue = getAverage(cA, cB) ; // cA, cB are complex
Matrix matrixValue = getAverage(mA, mB) ; // mA, mB are Matrix
// Java primitive/advanced types
// It won't really work in Java, even with generics. Sorry.
ओवरलोडिंग पर चर्चा करते संचालक
अब जब हमने ऑपरेटर ओवरलोडिंग का उपयोग करके C ++ कोड के बीच उचित तुलना देखी है, और जावा में समान कोड है, तो अब हम एक अवधारणा के रूप में "ऑपरेटर ओवरलोडिंग" पर चर्चा कर सकते हैं।
कंप्यूटर से पहले ऑपरेटर ओवरलोडिंग मौजूद है
बाहर भी कंप्यूटर विज्ञान के, वहाँ ऑपरेटर ओवरलोडिंग है: उदाहरण के लिए, गणित में, ऑपरेटरों की तरह +
, -
, *
, आदि अतिभारित रहे हैं।
दरअसल, ऑपरेंड्स के प्रकार (संख्यात्मक, वैक्टर, क्वांटम वेव फ़ंक्शंस, मैट्रिसेस, आदि) के आधार पर +
, के -
, का *
, आदि में परिवर्तन होता है।
हम में से अधिकांश, हमारे विज्ञान पाठ्यक्रमों के हिस्से के रूप में, ऑपरेटरों के लिए कई महत्व सीखते हैं, जो ऑपरेंड के प्रकारों पर निर्भर करते हैं। क्या हमने उन्हें भ्रमित किया, उन्हें?
ऑपरेटर ओवरलोडिंग उसके ऑपरेंड पर निर्भर करता है
यह ऑपरेटर ओवरलोडिंग का सबसे महत्वपूर्ण हिस्सा है: जैसे गणित में, या भौतिकी में, ऑपरेशन इसके ऑपरेंड्स के प्रकारों पर निर्भर करता है।
तो, ऑपरेंड के प्रकार को जानें, और आप ऑपरेशन के प्रभाव को जान पाएंगे।
यहां तक कि सी और जावा में (हार्ड-कोडित) ऑपरेटर ओवरलोडिंग है
सी में, एक ऑपरेटर का वास्तविक व्यवहार उसके ऑपरेंड के अनुसार बदल जाएगा। उदाहरण के लिए, दो पूर्णांक जोड़ना दो युगल, या एक पूर्णांक और एक डबल जोड़ने से अलग है। यहां तक कि संपूर्ण सूचक अंकगणितीय डोमेन भी है (कास्टिंग के बिना, आप एक सूचक को पूर्णांक में जोड़ सकते हैं, लेकिन आप दो संकेत नहीं जोड़ सकते हैं ...)।
जावा में, कोई सूचक अंकगणित नहीं है, लेकिन किसी को फिर भी +
ऑपरेटर के बिना स्ट्रिंग संयोजन मिला "ऑपरेटर ओवरलोडिंग बुराई है" पंथ में एक अपवाद का औचित्य साबित करने के लिए पर्याप्त हास्यास्पद होगा।
यह सिर्फ इतना है कि आप एक (ऐतिहासिक कारणों से) या जावा ( व्यक्तिगत कारणों से , नीचे देखें) कोडर के रूप में, आप अपना स्वयं का प्रदान नहीं कर सकते।
सी ++ में, ऑपरेटर ओवरलोडिंग वैकल्पिक नहीं है ...
C ++ में, ऑपरेटर के लिए निर्मित प्रकार संभव नहीं है अधिक भार (और यह एक अच्छी बात है), लेकिन उपयोगकर्ता-निर्धारित प्रकार हो सकता है उपयोगकर्ता परिभाषित ऑपरेटर ओवरलोड हो सकते हैं।
जैसा कि पहले ही कहा गया है, सी ++ में, और जावा के विपरीत, उपयोगकर्ता-प्रकार को भाषा के द्वितीय श्रेणी के नागरिक नहीं माना जाता है, जब अंतर्निहित प्रकारों की तुलना में। इसलिए, यदि बिल्ट-इन प्रकार के ऑपरेटर हैं, तो उपयोगकर्ता प्रकार उन्हें भी सक्षम होना चाहिए।
सच्चाई यह है कि, है की तरह toString()
, clone()
, equals()
तरीकों जावा के लिए कर रहे हैं ( यानी अर्ध मानक की तरह ), सी ++ ऑपरेटर ओवरलोडिंग सी की बहुत बहुत हिस्सा ++ है कि यह उल्लेख जावा तरीकों से पहले मूल सी ऑपरेटर के रूप में प्राकृतिक है, या के रूप में हो जाता है।
टेम्पलेट प्रोग्रामिंग के साथ संयुक्त, ऑपरेटर ओवरलोडिंग एक प्रसिद्ध डिजाइन पैटर्न बन जाता है। वास्तव में, आप अपने स्वयं के वर्ग के लिए अतिभारित ऑपरेटरों और ओवरलोडिंग ऑपरेटरों का उपयोग किए बिना एसटीएल में बहुत दूर नहीं जा सकते।
... लेकिन इसका दुरुपयोग नहीं होना चाहिए
ऑपरेटर ओवरलोडिंग को ऑपरेटर के शब्दार्थ का सम्मान करने का प्रयास करना चाहिए। एक +
ऑपरेटर में घटाना न करें (जैसा कि "किसी add
फ़ंक्शन में घटाना नहीं है ", या "एक clone
विधि में वापसी बकवास ")।
कास्ट ओवरलोडिंग बहुत खतरनाक हो सकती है क्योंकि वे अस्पष्टता पैदा कर सकते हैं। इसलिए उन्हें वास्तव में अच्छी तरह से परिभाषित मामलों के लिए आरक्षित होना चाहिए। के रूप में, &&
और ||
जब तक आप वास्तव में आप क्या कर रहे हैं, तब तक उन्हें अधिभार न डालें, जैसा कि आप शॉर्ट सर्किट मूल्यांकन खो देंगे जो देशी ऑपरेटर &&
और ||
आनंद लेते हैं।
तो ... ठीक है ... फिर यह जावा में क्यों संभव नहीं है?
क्योंकि जेम्स गोसलिंग ने ऐसा कहा:
मैंने ऑपरेटर को काफी व्यक्तिगत पसंद के रूप में ओवरलोडिंग छोड़ दिया क्योंकि मैंने बहुत से लोगों को सी ++ में इसका दुरुपयोग करते देखा था।
जेम्स गोस्लिंग। स्रोत: http://www.gotw.ca/publications/c_family_interview.htm
कृपया नीचे दिए गए स्ट्रॉस्ट्रुप के साथ गोसलिंग के पाठ की तुलना करें:
कई सी ++ डिजाइन के फैसले लोगों को किसी विशेष तरीके से काम करने के लिए मजबूर करने के लिए मेरी नापसंदगी में अपनी जड़ें रखते हैं [...] अक्सर, मुझे व्यक्तिगत रूप से नापसंद एक विशेषता को रेखांकित करने के लिए लुभाया गया था, मैंने ऐसा करने से परहेज किया क्योंकि मुझे नहीं लगता था कि मेरे पास था दूसरों पर अपना विचार रखने का अधिकार ।
बजरने स्ट्रॉस्ट्रुप। स्रोत: सी ++ का डिजाइन और विकास (1.3 सामान्य पृष्ठभूमि)
क्या ऑपरेटर ओवरलोडिंग से जावा को लाभ होगा?
कुछ वस्तुओं को ऑपरेटर ओवरलोडिंग (कंक्रीट या संख्यात्मक प्रकार, जैसे बिगडीकल, जटिल संख्या, मैट्रिस, कंटेनर, पुनरावृत्त, तुलनित्र, पार्सर आदि) से बहुत लाभ होगा।
C ++ में, आप Stroustrup की विनम्रता के कारण इस लाभ से लाभ उठा सकते हैं। जावा में, आप बस गोस्लिंग की व्यक्तिगत पसंद के कारण खराब हो गए हैं ।
क्या इसे जावा में जोड़ा जा सकता है?
जावा में अब ऑपरेटर ओवरलोडिंग को न जोड़ने के कारणों में आंतरिक राजनीति का मिश्रण हो सकता है, फीचर के लिए एलर्जी, डेवलपर्स के अविश्वास (आप जानते हैं, सबोटूर जो जावा टीमों को परेशान करते हैं ...), पिछले जेवीएस के साथ संगतता, सही विनिर्देश आदि लिखने का समय।
इसलिए इस सुविधा के लिए अपनी सांस रोक कर न रखें ...
लेकिन वे इसे सी # में करते हैं !!!
हाँ ...
हालांकि यह दोनों भाषाओं के बीच एकमात्र अंतर होने से बहुत दूर है, यह कभी भी मुझे लुभाने में विफल नहीं होता है।
जाहिरा तौर पर, सी # लोग, उनके साथ "हर आदिम एक है struct
, और struct
ऑब्जेक्ट से व्युत्पन्न है" , इसे पहले प्रयास में सही मिला।
उपयोग किए गए परिभाषित ऑपरेटर ओवरलोडिंग के खिलाफ सभी FUD के बावजूद, निम्न भाषाएं इसका समर्थन करती हैं: स्काला , डार्ट , पायथन , एफ # , सी # , डी # , अल्गोल 68 , स्मॉलटॉक , ग्रूवी , पर्ल 6 , सी ++, रूबी , हास्केल , MATLAB , एफिल , लुआ , क्लोजर , फोरट्रान 90 , स्विफ्ट , एडा , डेल्फी 2005 ...
इतनी सारी भाषाएं, इतने सारे अलग-अलग (और कभी-कभी विरोध) दर्शन के साथ, और फिर भी वे सभी उस बिंदु पर सहमत हैं।
सोच के लिए भोजन...