2013-02-03 40 views
11

मैं अपने सिर दौर पाने के लिए जावा का चयन करता है जो विधि निष्पादित किया जाता है कोशिश कर रहा हूँ:जावा ओवरलोडिंग विधि चयन

//Example 1 prints Square:add(Figure) 
Figure fs = new Square(); 
fs.add(fs); 

//Example 2 prints Square:add(Figure) 
Rectangle rs = new Square(); 
rs.add(fs); 

//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square) 
rs.add(new Square()); 

//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure) 
Square ss = new Square(); 
ss.add(rs); 

class Figure 
{ 
    public void add(Figure f){ System.out.println("Figure:add(Figure)"); } 
} 

class Rectangle extends Figure 
{ 
    @Override 
    public void add(Figure f){ System.out.println("Rectangle:add(Figure)"); } 
    public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); } 
} 

class Square extends Rectangle 
{ 
    @Override 
    public void add(Figure f){ System.out.println("Square:add(Figure)"); } 
    public void add(Square s){ System.out.println("Square:add(Square)"); } 
} 

मैं here क्या सीखा है

  • विधि हस्ताक्षर के आधार पर निर्धारित हो जाता है संकलित समय डेटा प्रकार
  • वास्तविक विधि लागू वस्तु जिस विधि को विधि कहा जाता है उस गतिशील प्रकार पर निर्भर करता है।

उस आधार पर, पहले दो कॉल का परिणाम अपेक्षा के अनुरूप है। हालांकि, मैं उदाहरण 3 और 4 के परिणाम को समझ नहीं पा रहा हूं।

ऐसा लगता है कि यह java language specification में निर्दिष्ट है, लेकिन मुझे यह समझ में नहीं आता है।

+1

इस असाइनमेंट प्रश्न के लेखक के रूप में मैं पुष्टि कर सकता हूं कि प्रदान किए गए उत्तर सही हैं। – Dominik

उत्तर

15

हालांकि, मैं उदाहरण के लिए 3 और 4.

ठीक है का परिणाम समझ में नहीं आता, के व्यक्तिगत रूप से उन पर नजर डालते हैं।

उदाहरण 3

//Example 3 prints Rectangle:add(Rectangle). Expected Square:add(Square) 
rs.add(new Square()); 

महत्वपूर्ण भागों संकलन समय भाव rs और new Square() की प्रकार हैं।

rs केवल, Rectangle के रूप में घोषित किया जाता है तो संकलक तरीकों Rectangle और उसके सुपर-क्लास द्वारा घोषित पर दिखेगा:

public void add(Figure f) 
public void add(Rectangle r) 

अभिव्यक्ति new Square()Square है के प्रकार, इसलिए दोनों तरीके हैं लागू - लेकिन दूसरा एक और विशिष्ट है।

तो संकलक rs पर ऑब्जेक्ट पर add(Rectangle) पर कॉल करेगा। यह संकलन समय के लिए है।

निष्पादन समय, rs का मूल्य Square का एक उदाहरण के लिए संदर्भित करता है - लेकिन Square पर हावी नहीं होता add(Rectangle) तो विधि उठाया Rectangle में दिया गया है:

public void add(Rectangle r){ System.out.println("Rectangle:add(Rectangle)"); } 

उदाहरण 4

//Example 4 prints Rectangle:add(Rectangle). Expected Square:add(Figure) 
Square ss = new Square(); 
ss.add(rs); 

फिर, चलिए संकलित समय के प्रकारों पर विचार करें ... ss प्रकार 012 है, और rs टाइप Rectangle (संकलन-समय प्रकार, याद रखें) है।

तरीकों Square और उसके सुपर-क्लास द्वारा घोषित कर रहे हैं:

public void add(Figure f) 
public void add(Rectangle r) 
public void add(Square s) 

rs का संकलन समय प्रकार के रूप में केवल Rectangle (नहीं Square), पहले दो तरीकों लागू होते हैं, लेकिन तीसरे नहीं है । इसलिए, फिर, add(Rectangle) संकलन समय पर चुना जाता है (क्योंकि यह add(Figure) से अधिक विशिष्ट है)।

फिर, ss के निष्पादन के समय प्रकार Square, जो add(Rectangle) पर हावी नहीं होता है, इसलिए Rectangle में कार्यान्वयन किया जाता है।

मुझे बताएं कि यहां कुछ भी भ्रमित है - यदि आप किस हिस्से के बारे में विशिष्ट हो सकते हैं, तो यह बहुत अच्छा होगा।

3
rs.add(new Square()); 

घोषित प्रकार का आर आयताकार है। तो यह आयत में एक विधि और स्क्वायर के साथ संगत स्क्वायर के साथ संगत स्क्वायर या एक प्रकार के सभी सुपरक्लास लेता है। सबसे विशिष्ट एक add(Rectangle) है क्योंकि स्क्वायर एक आयताकार है, और चूंकि आयत चित्रा से अधिक विशिष्ट है।

Square ss = new Square(); 
ss.add(rs); 

स्क्वायर में एक विधि add(Rectangle) और सभी सुपर कक्षाओं के लिए लग रहा है। Rectangle.add(Rectangle) चुना गया है, क्योंकि Square.add(Square) लागू नहीं होता है (एक आयताकार स्क्वायर नहीं है), और Square.add(Figure) कम विशिष्ट है।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^