क्या ओवरराइड तरीके रिटर्न प्रकार में भिन्न हो सकते हैं?


134

क्या ओवरराइड विधियों में अलग-अलग रिटर्न प्रकार हो सकते हैं ?


2
यदि आपके पास समान या संकरा रिटर्न प्रकार नहीं है तो आपको मिलेगा:error: method() in subclass cannot override method() in superclass
Quazi Irfan

जवाबों:


176

जावा ओवरराइड विधियों के लिए * सहसंयोजक रिटर्न प्रकार का समर्थन करता है । इसका मतलब यह है कि ओवरराइड की गई विधि में अधिक विशिष्ट रिटर्न प्रकार हो सकता है । यानी, जब तक आप जिस तरह से ओवरराइड कर रहे हैं, उस प्रकार के रिटर्न प्रकार पर नया रिटर्न टाइप करने की अनुमति है।

उदाहरण के लिए:

class ShapeBuilder {
    ...
    public Shape build() {
    ....
}

class CircleBuilder extends ShapeBuilder{
    ...
    @Override
    public Circle build() {
    ....
}

यह जावा भाषा विशिष्टता के खंड of.ification.५ में निर्दिष्ट है :

यदि रिटर्न प्रकार संदर्भ प्रकार हैं, तो रिटर्न प्रकार उन तरीकों के बीच भिन्न हो सकते हैं जो एक-दूसरे को ओवरराइड करते हैं। प्रतिफल-प्रकार-प्रतिस्थापन की धारणा सहसंयोजक रिटर्न का समर्थन करती है, अर्थात, वापसी प्रकार की विशेषज्ञता एक उपप्रकार की ओर।

वापसी प्रकार आर 1 के साथ एक विधि घोषणा डी 1 रिटर्न प्रकार आर 2 के साथ एक और विधि डी 2 के लिए रिटर्न-टाइप-प्रतिस्थापन योग्य है, यदि और केवल यदि निम्न स्थितियां हैं:

  • यदि आर 1 शून्य है तो आर 2 शून्य है।

  • यदि आर 1 एक आदिम प्रकार है, तो आर 2 आर 1 के समान है।

  • यदि R1 एक संदर्भ प्रकार है तो:

    • R1 या तो R2 का उपप्रकार है या R1 को अनियंत्रित रूपांतरण ()5.1.9) द्वारा R2 के उपप्रकार में परिवर्तित किया जा सकता है, या

    • आर 1 = | आर 2 |

("| R2 |", R2 के विलोपन को संदर्भित करता है, जैसा कि JLS के of4.6 में परिभाषित किया गया है ।)


* जावा 5 से पहले, जावा में अपरिवर्तनीय वापसी प्रकार थे, जिसका मतलब था कि जिस प्रकार से ओवरराइड किया जा रहा है उस विधि से पूरी तरह मेल खाने के लिए आवश्यक एक प्रकार का ओवरराइड।


26

हाँ यह अलग हो सकता है लेकिन उनकी कुछ सीमाएँ हैं।

जावा 5.0 से पहले, जब आप एक विधि को ओवरराइड करते हैं, तो पैरामीटर और रिटर्न प्रकार दोनों को बिल्कुल मेल खाना चाहिए। जावा 5.0 में, यह एक नई सुविधा का परिचय देता है जिसे सहसंयोजक वापसी प्रकार कहा जाता है। आप एक ही हस्ताक्षर के साथ एक विधि को ओवरराइड कर सकते हैं लेकिन लौटाए गए ऑब्जेक्ट का उपवर्ग लौटाते हैं। दूसरे शब्दों में, एक उपवर्ग में एक विधि एक वस्तु को लौटा सकती है जिसका प्रकार सुपरक्लास में उसी हस्ताक्षर के साथ विधि द्वारा लौटाए गए प्रकार का उपवर्ग है।


20

हां, यदि वे एक उपप्रकार लौटाते हैं। यहाँ एक उदाहरण है:

package com.sandbox;

public class Sandbox {

    private static class Parent {
        public ParentReturnType run() {
            return new ParentReturnType();
        }
    }

    private static class ParentReturnType {

    }

    private static class Child extends Parent {
        @Override
        public ChildReturnType run() {
            return new ChildReturnType();
        }
    }

    private static class ChildReturnType extends ParentReturnType {
    }
}

यह कोड संकलित करता है और चलाता है।


9

मोटे तौर पर ओवरराइडिंग विधि का हाँ रिटर्न टाइप अलग हो सकता है। लेकिन यह सीधे तौर पर आगे नहीं है क्योंकि इसमें कुछ मामले शामिल हैं।

केस 1: यदि रिटर्न प्रकार एक आदिम डेटा प्रकार या शून्य है।

आउटपुट: यदि रिटर्न प्रकार शून्य या आदिम है तो डेटा प्रकार की मूल श्रेणी विधि और ओवरराइडिंग विधि समान होनी चाहिए। उदाहरण के लिए यदि रिटर्न टाइप इंट, फ्लोट, स्ट्रिंग है तो यह समान होना चाहिए

केस 2: यदि रिटर्न टाइप किया जाता है तो डेटा टाइप:

आउटपुट: यदि मूल श्रेणी विधि का रिटर्न प्रकार व्युत्पन्न प्रकार है, तो ओवरराइडिंग विधि का रिटर्न प्रकार एक ही व्युत्पन्न डेटा प्रकार है जो व्युत्पन्न डेटा प्रकार के लिए उपवर्ग का है। जैसे मान लीजिए कि मेरे पास एक वर्ग ए है, बी ए के लिए एक उपवर्ग है, सी बी के लिए एक उपवर्ग है और डी सी के लिए एक उपवर्ग है; फिर यदि सुपर क्लास टाइप A लौट रहा है, तो ओवरराइडिंग विधि उपवर्ग है, A, B, C या D प्रकार यानी सब प्रकार वापस कर सकते हैं। इसे सहसंयोजक भी कहा जाता है।


आपकी यह टिप्पणी अस्पष्ट है कि एक वर्ग एबी के पास सबक्लास है, बीडी के लिए उपवर्ग है, इसका क्या मतलब है कि कक्षा एबी एसी या ए का उपवर्ग है, बी ए का उपवर्ग है, सी का अर्थ है इसका भ्रमित होना
दिनेश कांडपाल

5

हाँ यह संभव है .. रिटर्न प्रकार केवल तभी अलग हो सकता है जब पैरेंट क्लास मेथड रिटर्न टाइप
एक सुपर टाइप ऑफ चाइल्ड क्लास मेथड रिटर्न टाइप हो ..
मतलब

class ParentClass {
    public Circle() method1() {
        return new Cirlce();
    }
}

class ChildClass extends ParentClass {
    public Square method1() {
        return new Square();
    }
}

Class Circle {

}

class Square extends Circle {

}


यदि यह है तो अलग रिटर्न प्रकार की अनुमति दी जा सकती है ...


2

खैर, जवाब हाँ है ... और नहीं।

सवाल पर निर्भर करता है। यहां हर किसी ने जावा> = 5 के बारे में उत्तर दिया, और कुछ ने उल्लेख किया कि जावा <5 में सहसंयोजक वापसी प्रकार नहीं हैं।

वास्तव में, जावा भाषा की युक्ति> = 5 इसका समर्थन करती है, लेकिन जावा रनटाइम नहीं करता है। विशेष रूप से, JVM को कोविरेंट रिटर्न प्रकारों का समर्थन करने के लिए अद्यतन नहीं किया गया था।

तब जो "चतुर" चाल के रूप में देखा गया था, लेकिन जावा के इतिहास में सबसे खराब डिजाइन निर्णयों में से एक था, जावा 5 ने जेवीएम या क्लासफाइल कल्पना को संशोधित किए बिना नई भाषा सुविधाओं का एक गुच्छा लागू किया। इसके बजाय सभी सुविधाओं को javac में चालबाज़ी के साथ लागू किया गया था: संकलक नेस्टेड / इनर वर्ग के लिए सादे कक्षाएं बनाता है / उपयोग करता है, जेनेरिक के लिए टाइप इरेज़र और कास्ट, नेस्टेड के लिए सिंथेटिक एक्सेसर्स / आंतरिक "निजी" मैत्री ", बाहरी 'इस' के लिए सिंथेटिक इंस्टेंस फ़ील्ड संकेत, '.class' शाब्दिक, आदि के लिए सिंथेटिक स्थिर क्षेत्र, आदि।

और covariant रिटर्न प्रकार अभी तक अधिक संश्लिष्ट चीनी है जो जावाक द्वारा जोड़े जाते हैं।

उदाहरण के लिए, जब यह संकलन हो:

class Base {
  Object get() { return null; }
}

class Derived extends Base {
  @Override
  @SomeAnnotation
  Integer get() { return null; }
}

javac व्युत्पन्न वर्ग में दो तरीके प्राप्त करेगा:

Integer Integer:Derived:get() { return null; }
synthetic bridge Object Object:Derived:get() { return Integer:Derived:get(); }

उत्पन्न ब्रिज विधि (चिह्नित syntheticऔर bridgeबायटेकोड में) वास्तव में ओवरराइड होती है Object:Base:get()क्योंकि, जेवीएम के लिए, विभिन्न रिटर्न प्रकार के तरीके पूरी तरह से स्वतंत्र हैं और एक दूसरे को ओवरराइड नहीं कर सकते हैं। अपेक्षित व्यवहार प्रदान करने के लिए, पुल आपके "वास्तविक" तरीके को कॉल करता है। ऊपर दिए गए उदाहरण में, javac @SomeAnnotation के साथ Derived में पुल और वास्तविक दोनों तरीकों की व्याख्या करेगा।

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

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

इसलिए आपके प्रश्न का पूरी तरह से उत्तर देने के लिए: JVM सहसंयोजक रिटर्न प्रकारों का समर्थन नहीं करता है, लेकिन javac> = 5 इसे मीठे वाक्यात्मक चीनी के लेप के साथ संकलित समय पर देता है।


1

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

नमूना कोड


                                                                                                            class Alpha {
          Alpha doStuff(char c) {
                  return new Alpha();
              }
           }
             class Beta extends Alpha {
                    Beta doStuff(char c) { // legal override in Java 1.5
                    return new Beta();
                    }
             } } 
जावा 5, यह कोड संकलित करेगा। यदि आप इस कोड को 1.4 संकलक के साथ संकलित करने का प्रयास कर रहे थे, तो असंगत रिटर्न प्रकार का उपयोग करने का प्रयास करेंगे - sandeep1987 1 मिनट पहले


1

अन्य उत्तर सभी सही हैं, लेकिन आश्चर्यजनक रूप से सभी सैद्धांतिक पहलू को यहां छोड़ रहे हैं: रिटर्न प्रकार भिन्न हो सकते हैं, लेकिन वे केवल लिस्कोव सब्सट्रेटिंग सिद्धांत के कारण सुपर क्लास में उपयोग किए जाने वाले प्रकार को प्रतिबंधित कर सकते हैं ।

यह सुपर सरल है: जब आपके पास "क्लाइंट" कोड होता है जो कुछ विधि कहता है:

int foo = someBar.bar();

फिर उपरोक्त को काम करना है (और कुछ वापस करना है जो कि intकोई बात नहीं है जिसे लागू bar()किया जाता है)।

अर्थ: यदि कोई बार उपवर्ग है जो ओवरराइड करता है bar()तो आपको अभी भी कुछ ऐसा लौटना होगा जो "कॉलर कोड" को नहीं तोड़ता है।

दूसरे शब्दों में: मान लें कि आधार bar()को वापस लौटना है। तब एक उपवर्ग वापस आ सकता है short- लेकिन longइसलिए नहीं कि कॉल करने वाले एक shortमूल्य के साथ ठीक काम करेंगे , लेकिन नहीं long!


0

वापसी का प्रकार वैसा ही होना चाहिए, या उसका उप-प्रकार होना चाहिए, सुपरक्लास में मूल ओवरराइड विधि में घोषित वापसी प्रकार।


5
आपको अपने दो उत्तरों को संयोजित करना चाहिए।
दिबांग

0

हाँ, यह संभव हो सकता है

class base {

 base show(){

System.out.println("base class");

return new base();

}
}

class sub extends base{

sub show(){

    System.out.println("sub class");

    return new sub();

 }
}

class inheritance{

 public static void main(String []args) {

        sub obj=new sub();

            obj.show();
 }
}

0

हाँ। ओवरराइड तरीकों के लिए अलग-अलग रिटर्न टाइप करना संभव है।

लेकिन सीमाएं यह हैं कि ओवरराइड विधि में एक वापसी प्रकार होना चाहिए जो वास्तविक विधि के रिटर्न प्रकार का अधिक विशिष्ट प्रकार है।

सभी उत्तरों में ओवरराइड विधि के उदाहरण दिए गए हैं, जिसमें एक रिटर्न प्रकार है जो वास्तविक विधि के रिटर्न प्रकार का एक उपवर्ग है।

उदाहरण के लिए :

public class Foo{

   //method which returns Foo
  Foo getFoo(){
      //your code         
  }

}

 public class subFoo extends Foo{

  //Overridden method which returns subclass of Foo
  @Override
  subFoo getFoo(){
      //your code         
  }

}

लेकिन यह केवल उपवर्ग तक सीमित नहीं है। एक इंटरफ़ेस को लागू करने वाले कुछ वर्ग एक विशिष्ट प्रकार के इंटरफ़ेस हैं और इस प्रकार एक वापसी प्रकार हो सकता है जहाँ इंटरफ़ेस की अपेक्षा की जाती है।

उदाहरण के लिए :

public interface Foo{

   //method which returns Foo
  Foo getFoo();

}

 public class Fizz implements Foo{

  //Overridden method which returns Fizz(as it implements Foo)
  @Override
  Fizz getFoo(){
      //your code         
  }

}

0
class Phone {
    public Phone getMsg() {
        System.out.println("phone...");
        return new Phone();
    }
}

class Samsung extends Phone{
    @Override
    public Samsung getMsg() {
        System.out.println("samsung...");
        return new Samsung();
    }
    
    public static void main(String[] args) {
        Phone p=new Samsung();
        p.getMsg();
    }
}

यह प्रश्न का उत्तर कैसे देता है?
अनब्रांडेड मैनचेस्टर

यह विभिन्न प्रकार के रिटर्न का उदाहरण है।
पार्थ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.