1. टाइपकास्टिंग

चर जो संदर्भ प्रकार (वर्ग) को संग्रहीत करते हैं, उन्हें भी विभिन्न प्रकारों में परिवर्तित किया जा सकता है। लेकिन यह केवल एक ही प्रकार के पदानुक्रम के भीतर काम करता है। आइए एक साधारण उदाहरण देखें। मान लीजिए कि हमारे पास निम्न वर्ग पदानुक्रम है, जिसमें निम्न वर्ग ऊपर की कक्षाओं को इनहेरिट करते हैं।

टाइपकास्टिंग

संदर्भ प्रकारों के साथ-साथ आदिम प्रकार के टाइपकास्टिंग को भी चौड़ा और संकुचित करने के रूप में वर्गीकृत किया गया है।

हम देखते हैं कि बिल्ली वर्ग पालतू वर्ग को विरासत में मिला है, और पालतू वर्ग बदले में पशु वर्ग को विरासत में मिला है।

अगर हम इस तरह कोड लिखते हैं:

Animal kitten = new Cat();

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

एक संकुचित रूपांतरण (या स्पष्ट कास्ट) विपरीत दिशा में होता है:

Cat cat = (Cat) kitten;

हमने स्पष्ट रूप से संकेत दिया है कि हम बिल्ली के प्रकार के लिए बिल्ली का बच्चा चर (जिसका प्रकार पशु है ) में संग्रहीत संदर्भ डालना चाहते हैं।



2. किसी वस्तु के प्रकार की जाँच करना

लेकिन यहां आपको बेहद सावधान रहने की जरूरत है। अगर आप यह करते हैं:

Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;

कंपाइलर इस कोड को अनुमति देगा, लेकिन प्रोग्राम चलने पर एक त्रुटि होगी ! जेवीएम एक अपवाद फेंक देगा:

Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf

कैट ऑब्जेक्ट के संदर्भ केवल वेरिएबल्स में संग्रहीत किए जा सकते हैं जिनका प्रकार कैट क्लास का पूर्वज है: पेट, एनिमल या ऑब्जेक्ट।

ऐसा क्यों?

यहाँ प्रासंगिक बिंदु यह है कि एक वस्तु संदर्भ का उपयोग उस वस्तु के तरीकों और चर को संदर्भित करने के लिए किया जाता है । और अगर हम Cat ऑब्जेक्ट के संदर्भ को स्टोर करने के लिए किसी Animal चर का उपयोग करते हैं तो कोई समस्या नहीं होगी: Cat प्रकार में हमेशा पशु प्रकार के चर और तरीके होते हैं - यह उन्हें विरासत में मिला है!

लेकिन अगर JVM हमें वुल्फ वैरिएबल में कैट ऑब्जेक्ट के संदर्भ को स्टोर करने की इजाजत देता है, तो हमारे पास ऐसी स्थिति हो सकती है जहां हम ग्रेवॉल्फ वैरिएबल का उपयोग करने के लिए उस विधि को कॉल करने का प्रयास कर सकते हैं जो उस चर में संग्रहीत कैट ऑब्जेक्ट में मौजूद नहीं है। . इसलिए इस व्यवस्था की अनुमति नहीं है।

जावा में एक विशेष instanceofऑपरेटर है जो आपको यह जांचने देता है कि क्या कोई वस्तु एक निश्चित प्रकार की है और इसलिए उसे एक निश्चित प्रकार के चर में संग्रहीत किया जा सकता है। यह काफी सरल दिखता है:

variable instanceof Type

उदाहरण:

Animal beast = new Cat();
if (beast instanceof Wolf)
{
   Wolf grayWolf = (Wolf) beast;
}

यह कोड त्रुटियों का कारण नहीं बनेगा - रनटाइम पर भी।

यहाँ कुछ और उदाहरण दिए गए हैं जो स्थिति को स्पष्ट करते हैं:

चौड़ा प्रकार रूपांतरण विवरण
Cow cow = new Whale();

यह एक क्लासिक चौड़ा रूपांतरण है - किसी प्रकार के रूपांतरण ऑपरेटर की आवश्यकता नहीं है। अब केवल कक्षा में परिभाषित विधियों को ही वस्तु Cowपर बुलाया जा सकता है ।Whale

cowचर पर , कंपाइलर आपको केवल उन विधियों को कॉल करने देगा जो उसके प्रकार ( Cowकक्षा) में हैं।

संकीर्ण प्रकार रूपांतरण
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
क्लासिक संकरा रूपांतरण: आपको एक प्रकार की जाँच और एक कास्ट ऑपरेटर जोड़ने की आवश्यकता है।
चर किसी वस्तु Cow cowके संदर्भ को संग्रहीत करता है । हम सत्यापित करते हैं कि यह मामला है , और फिर एक (संकुचित) प्रकार रूपांतरण करते हैं। या जैसा कि यह भी कहा जाता है: Whale
एक प्रकार कास्ट
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
आप ऑब्जेक्ट के प्रकार की जांच किए बिना संदर्भ प्रकार को सीमित कर सकते हैं।
यदि cowचर किसी वस्तु को संदर्भित करता है जो a नहीं है Whale, तो एक InvalidClassCastExceptionउत्पन्न होगा।


3. मूल विधि को कॉल करना: superकीवर्ड

पैरेंट क्लास के मेथड को ओवरराइड करते समय, कभी-कभी इसे अपने से बदलने के बजाय, हम केवल इसे थोड़ा सा सप्लीमेंट करना चाहते हैं।

यह अच्छा होगा यदि हम अपनी पद्धति में मूल वर्ग की विधि कर सकें, और फिर अपने स्वयं के कोड को निष्पादित कर सकें। या शायद पहले अपना कोड निष्पादित करें, और फिर मूल वर्ग की विधि को कॉल करें।

और जावा हमें बस यही करने देता है। अभिभावक वर्ग की विधि को कॉल करने के लिए, यह करें:

super.method(arguments);

उदाहरण:

class PeaceTime
{
   public double getPi()
   {
      return 3.14;
   }
}

class WarTime extends PeaceTime
{
   public double getPi()
   {
      return super.getPi()*2;  // 3.14*2
   }
}

युद्धकाल में, का मान Pi6 से अधिक हो सकता है! बेशक, हम मजाक कर रहे हैं, लेकिन यह उदाहरण दर्शाता है कि यह सब कैसे काम कर सकता है।

चीजों को थोड़ा स्पष्ट करने के लिए यहां कुछ और उदाहरण दिए गए हैं:

कोड विवरण
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.print("This is incorrect: ");
      super.printName();
      System.out.println("I'm a whale");
   }
}
Cowऔर Whaleकक्षाएं
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
स्क्रीन आउटपुट होगा:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

यह कठिन चीज है। ईमानदारी से, यह OOP की सबसे कठिन चीजों में से एक है । उस ने कहा, आपको इसे जानने और समझने की जरूरत है।