
"हाय, अमीगो!"
"लेकिन हम पहले ही नमस्ते कह चुके हैं, ऐली!"
"अरे, अपनी बुआ से बहस मत करना। 31वीं सदी में अगर आधे घंटे से ज्यादा किसी को नहीं देखा हो तो फिर से हैलो कहने का रिवाज है। इसलिए मुझे अपना एटीट्यूड मत दो!"
"वैसे भी, यह एक और दिलचस्प विषय का समय है: रोबोट प्रजनन!"
"ओ_ओ।"
"बस मज़ाक कर रहा हूँ, नया विषय गुमनाम आंतरिक वर्ग है ।"
"जावा में, कभी-कभी ऐसी परिस्थितियाँ होती हैं जहाँ आपको कई वर्गों को इनहेरिट करने के लिए एक क्लास की आवश्यकता होती है। चूंकि जावा मल्टीपल इनहेरिटेंस का समर्थन नहीं करता है, इसलिए उन्होंने आंतरिक कक्षाओं का उपयोग करके इस समस्या को हल किया है: हमारी कक्षा में, हम एक आंतरिक वर्ग की घोषणा करते हैं और बनाते हैं यह इनहेरिट करने के लिए हमें जिस भी वर्ग की आवश्यकता है, उसे इनहेरिट करता है। यहां एक उदाहरण दिया गया है:"
class Tiger extends Cat
{
public void tigerRun()
{
.....
}
public void startTiger()
{
TigerThread thread = new TigerThread();
thread.start();
}
class TigerThread extends Thread
{
public void run()
{
tigerRun();
}
}
}
"आइए एक और उदाहरण देखें:"
इसकी रन विधि को ओवरराइड करने के लिए हमें थ्रेड क्लास के उप-वर्ग की आवश्यकता है।"
"इसीलिए टाइगर क्लास में हमने टाइगर थ्रेड इनर क्लास घोषित किया, जो थ्रेड को इनहेरिट करता है और रन मेथड को ओवरराइड करता है।
"सुविधा के लिए, हमने टाइगर वर्ग में दो विधियों को परिभाषित किया: टाइगररुन और स्टार्ट टाइगर (जो थ्रेड के रन और स्टार्ट विधियों के अनुरूप हैं।"
"टाइगरस्टार्ट मेथड में, हम टाइगर थ्रेड ऑब्जेक्ट बनाते हैं और इसके स्टार्ट () मेथड को इनवॉइस करते हैं।"
"JVM एक नया थ्रेड बनाएगा जो टाइगर थ्रेड के रन मेथड को कॉल करने पर चलने लगेगा ।"
"यह विधि तब हमारी रन विधि को कॉल करती है: tigerRun ।"
"मैंने पहले धागे के साथ काम किया है, इसलिए यह सीधा लगता है।"
"क्या हमें टाइगररन और टाइगरस्टार्ट के तरीकों का नाम देना होगा?"
"नहीं, हम उन्हें रन और स्टार्ट कह सकते थे, लेकिन मैं यह भी दिखाना चाहता था कि हम थ्रेड को इनहेरिट नहीं कर रहे हैं। एक स्पष्टीकरण अधिक भ्रामक हो सकता है।"
"ठीक है। फिर मुझे लगता है कि मैं समझ गया। लेकिन अगर टाइगरस्टार्ट को दूसरी बार कॉल किया जाता है, तो हम दूसरा थ्रेड ऑब्जेक्ट बनाएंगे और शुरू करेंगे। क्या इसका मतलब यह नहीं है कि हमारे पास «एक बाघ दो अलग-अलग धागों पर चल रहा है»? "
"ठीक है, क्या तुम तेज नहीं हो! तुम सही हो, और यह अच्छा नहीं है। चलो इस तरह से कोड को फिर से लिखते हैं:"
class Tiger extends Cat
{
public void tigerRun()
{
.....
}
public void startTiger()
{
thread.start();
}
private TigerThread thread = new TigerThread();
private class TigerThread extends Thread
{
public void run()
{
tigerRun();
}
}
}
"यह बिल्कुल सही नहीं है। आप अभी भी इस तरह की एक विधि को दो बार कॉल नहीं कर सकते। लेकिन इस बार, कम से कम हम दूसरा थ्रेड नहीं बनाएंगे और ऐसा नहीं लगेगा कि सब कुछ ठीक है।"
"यह सही है। दूसरी बार जब टाइगर शुरू होता है, तो आपको एक अपवाद मिलेगा।"
"मैं पहले से ही गलतियों को तुमसे बेहतर पहचान रहा हूँ, ऐली!"
"हाँ, आप बहुत अच्छा कर रहे हैं। तो चलिए अनाम आंतरिक कक्षाओं की ओर बढ़ते हैं।"
"उपर्युक्त कोड के कई पहलुओं पर ध्यान दें:"
1) हमें थ्रेड क्लास विरासत में मिली है, लेकिन व्यावहारिक रूप से वहां कोई कोड लागू नहीं किया गया है। "यह अधिक था «हमें थ्रेड क्लास का वारिस करना पड़ा» के बजाय «हमें इसे विस्तारित करने के लिए विरासत में मिला»।
2) केवल एक टाइगर थ्रेड ऑब्जेक्ट बनाया जाएगा।
दूसरे शब्दों में, हमने केवल एक विधि को ओवरराइड करने और एक वस्तु बनाने के लिए कोड का एक पूरा गुच्छा लिखा।
क्या आपको याद है कि मैंने कंस्ट्रक्टर्स के आविष्कार के बारे में कैसे बात की थी?
कंस्ट्रक्टर्स से पहले | कंस्ट्रक्टर्स के बाद |
---|---|
|
|
"मैं देख रहा हूं कि कोड अधिक कॉम्पैक्ट हो गया है, लेकिन मुझे समझ नहीं आ रहा है कि क्या हो रहा है।"
"हम चार चीजों को एक में जोड़ सकते हैं:"
1) व्युत्पन्न वर्ग की घोषणा
2) विधि ओवरराइडिंग
3) एक चर की घोषणा
4) व्युत्पन्न वर्ग के उदाहरण का निर्माण।
"वास्तव में, हम जो कर रहे हैं वह दो ऑपरेशनों का संयोजन है: एक व्युत्पन्न वर्ग की घोषणा करना और उस वर्ग का एक उदाहरण बनाना।"
अनाम वर्ग के बिना | अनाम वर्ग के साथ |
---|---|
|
|
"आइए सिंटैक्स को फिर से देखें:"
Thread thread = new Thread();
Thread thread = new Thread()
{
};
"ध्यान दें कि हम केवल एक नए वर्ग को परिभाषित नहीं कर रहे हैं। हम एक चर बना रहे हैं - अंत में एक अर्धविराम है!"
"और अगर हम रन विधि को ओवरराइड करना चाहते हैं, तो हमें इसे लिखना होगा:"
Thread thread = new Thread()
{
public void run()
{
System.out.println("new run-method");
}
};
"आप जल्दी पकड़ लेते हैं। शाबाश!"
"धन्यवाद। क्या होगा यदि हमें अन्य विधियों की आवश्यकता है जो थ्रेड क्लास का हिस्सा नहीं हैं?"
"आप उन्हें लिख सकते हैं।"
"हालांकि गुमनाम, यह एक पूर्ण आंतरिक वर्ग है:"
जावा कोड | विवरण |
---|---|
|
लाल: चर बनाने के लिए कोड।
हरा: वस्तु बनाने के लिए कोड। नीला: अनाम व्युत्पन्न वर्ग के लिए कोड। |
"एक पूर्ण आंतरिक वर्ग?"
"तो मैं बाहरी वर्ग के चर का उपयोग कर सकता हूं?"
"बिल्कुल।"
"और मैं कन्स्ट्रक्टर को कुछ पास कर सकता हूं?"
"हाँ, लेकिन केवल सुपरक्लास के निर्माता के लिए तर्क:"
कक्षा | एक अनाम आंतरिक वर्ग का उदाहरण |
---|---|
|
|
"हम किसी और के कंस्ट्रक्टर में अपने खुद के पैरामीटर नहीं जोड़ सकते। लेकिन हम बाहरी वर्ग के चर का उपयोग कर सकते हैं, जो इस कमी के लिए अच्छी तरह से क्षतिपूर्ति करता है।"
"क्या होगा अगर मुझे अभी भी कन्स्ट्रक्टर में अन्य पैरामीटर जोड़ने की ज़रूरत है?"
"फिर एक सामान्य (गैर-गुमनाम) आंतरिक वर्ग घोषित करें और उसका उपयोग करें।"
"ठीक है, मैं उसके बारे में लगभग भूल ही गया था।"
"क्या होगा अगर मैं एक स्थिर चर घोषित करता हूं? क्या यह अनाम वर्ग को एक आंतरिक वर्ग के बजाय एक स्थिर नेस्टेड वर्ग बना देगा? दूसरे शब्दों में, क्या इसमें बाहरी वर्ग के संदर्भ की कमी होगी?"
"नहीं। यह एक अनाम आंतरिक वर्ग होगा। इन उदाहरणों को देखें।"
अनाम वर्ग के साथ | अनाम वर्ग के बिना |
---|---|
|
|
|
|
"मैं देख रहा हूँ। केवल स्थैतिक चर स्थिर होगा, वर्ग नहीं।"
"हां।"
"वास्तव में, कंपाइलर सभी अज्ञात आंतरिक कक्षाओं के लिए आंतरिक कक्षाएं बनाता है। इन कक्षाओं को आमतौर पर «1», «2», «3», आदि नाम दिया जाता है।
GO TO FULL VERSION