2009-01-30 16 views
5

मेरे पास जावा में विरासत और कास्टिंग के बारे में एक प्रश्न है। मैं निम्नलिखित दो उदाहरण वर्गों और एक परीक्षण वर्ग है, और मुझे कक्षाओं के बाद मेरे सवाल राज्य:जावा में विरासत और कास्टिंग

public class Automobile { 
    public int var; 

    public Automobile() { 
     var = 1; 
    } 

    public String toString() { 
     return "AUTOMOBILE: " + var; 
    } 
} 


public class Porsche extends Automobile { 
    public int var; 

    public Porsche() { 
     var = 2; 
    } 

    public String toString() { 
     return "PORSCHE: " + var; 
    } 
} 

public class Test { 
    public static void main (String [] args) { 
     Porsche p = new Porsche(); 
     Automobile a = new Automobile(); 

     System.out.println ("(Automobile) p = " + (Automobile)p); 

     System.out.println ("(Automobile) p.var = " + ((Automobile)p).var); 
    } 
} 

उत्पादन होता है:

(Automobile) p = PORSCHE: 2 
(Automobile) p.var = 1 

मैं क्यों दूसरा बयान में समझ में नहीं आता हम है 1. यह 2 होना चाहिए? क्योंकि के बाद मैं पहली बार बयान में ऑटोमोबाइल के लिए पी डाली मैं अभी भी p का प्रतिनिधित्व के रूप में PORSCHE: 2 मिल - मैं निम्नलिखित तरीके से इस बात को समझ:

फिर भी मैं ऑटोमोबाइल p को p casted है अपने 'मूल प्रकृति "रखता है - p है कक्षा पोर्श का एक वस्तु, लेकिन क्योंकि पोर्श ऑटोमोबाइल फैलाता है, हम कह सकते हैं कि पी एक ऑटोमोबाइल भी है। और इसलिए जब हमने इसे ऑटोमोबाइल को स्पष्ट रूप से डाला, तो यह में हमारे मामले का उपयोग जारी रखता है, हमारे मामले में पोर्श में परिभाषित विधि toString() है।

दूसरी ओर, अगर मैं क्या लिखना सही है, तो दूसरा प्रिंट बयान 2 देना चाहिए और नहीं 1.

अब यह मेरे लिए एक विरोधाभास के रूप लगता है, लेकिन जब से यह जावा में काम करता है, ऐसा लगता है कि मुझे समझ में नहीं आता कि कास्टिंग और विरासत प्रक्रिया के दौरान क्या चल रहा है।

उत्तर

16

मुझे विश्वास है कि आप वास्तव में जावा में चर को ओवरराइड नहीं कर सकते हैं। उप-वर्ग वास्तव में परिवर्तनीय var 'छुपाता है'।

जब आप Automobile पर जाते हैं, तो आपको var चर के सुपरक्लास 'संस्करण मिल रहे हैं। हालांकि, toString() विधि अभी भी var चर के उदाहरण के संस्करण को देख रही है।

यदि आपने पोर्श सबक्लास से public int var हटा दिया है तो इसे अपेक्षा के अनुसार काम करना चाहिए।

यह ध्यान दिया जाना चाहिए कि सार्वजनिक आवृत्ति चर का उपयोग करना अच्छा अभ्यास नहीं है, आपको हमेशा encapsulation उचित करने के लिए गेटर्स/सेटर्स बनाना चाहिए।

5

परिवर्तनीय var का छायांकन।

आपका Porche.varAutomobile.var से भिन्न भिन्नता है।

Porsche.toString() विधि Porsche.var का उपयोग करती है, जबकि कलाकार Automobile संस्करण का उपयोग करने के लिए कंपाइलर को बताता है।

2

फ़ील्ड तक पहुंच polymorphic नहीं है - यह केवल अभिव्यक्ति के संकलन समय प्रकार पर निर्भर करता है।

अभिव्यक्ति ((ऑटोमोबाइल) पी) ने समय प्रकार ऑटोमोबाइल संकलित किया है, इसलिए इसके फ़ील्ड का उपयोग किया जाता है।

1

दोनों वर्गों में परिवर्तनीय "var" घोषित करना, वास्तव में स्मृति में दो फ़ील्ड बनाता है।

"पोर्श" के एक उदाहरण में स्मृति में दो "var" फ़ील्ड होंगे, "पोर्श" वर्ग में से एक और सुपर क्लास "ऑटोमोबाइल" में से एक होगा। जब आप ज्ञात "पोर्श" उदाहरण से "var" का संदर्भ लेते हैं तो सुपर क्लास का "var" फ़ील्ड छिपा हुआ होता है।यदि आप इस उदाहरण को "ऑटोमोबाइल" में डालते हैं और "var" फ़ील्ड का संदर्भ देते हैं, तो आप "ऑटोमोबाइल" के var फ़ील्ड को संदर्भित करते हैं।

फ़ील्ड में कोई ओवरराइडिंग नहीं है। एक ही नाम वाले नए फ़ील्ड सुपर क्लास के खेतों को ढंकते हैं।

अपेक्षित परिणाम प्राप्त करने के लिए आपको "पोर्श" कक्षा में "var" फ़ील्ड घोषित नहीं करना चाहिए।

0
हालांकि

:

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

class A { 
int a1,a2; 
public A(){} 


    public static A getInstance() { 
    return new B() ; 
    } 
} 
class B { 
int b1,b2; 
    public B() {} 

} 
class Test{ 

public static void main (String [] args) { 

    A theA = A.getInstance() ; //here theA has only a1,a2 as attributes 
    B theB = (B)theA // here theB has b1,a2 and a1,a2 as attributes 
    } 


}