2012-07-19 18 views
7

में एक अमूर्त विधि को ओवरराइड करना मुझे वास्तव में यह पता होना चाहिए, लेकिन किसी कारण से मैं निम्नलिखित को समझ नहीं पा रहा हूं।जावा: सबक्लास

protected abstract RuleDTO createRowToBeCloned(RuleDTO ruleDTO); 

इस प्रकार मैं भी अन्य वर्ग है:

मेरे सार वर्ग निम्नलिखित सार विधि शामिल

EvaluationRuleDTO extends from RuleDTO 

तब मेरे सार वर्ग का एक उपवर्ग में मैं निम्नलिखित कार्यान्वयन है जो है "सुपरटाइप विधि को ओवरराइड या कार्यान्वित करने" के कारण अनुमति नहीं है:

protected EvaluationRuleDTO createRowToBeCloned(EvaluationRuleDTO ruleDTO) { 

हालांकि, निम्नलिखित अनुमति दी है:

protected EvaluationRuleDTO createRowToBeCloned(RuleDTO ruleDTO) { 

मुझे पता है यह शायद एक बुनियादी सवाल है, लेकिन मैं एक छोटे से हतप्रभ हूं। मैं ओवरडॉइड विधि में रुलेडीटीओ के उप-वर्ग को कैसे वापस कर सकता हूं, लेकिन मैं सबक्लास में पास नहीं कर सकता हूं?

धन्यवाद

उत्तर

11

आप लिस्कोव सिद्धांत तोड़ रहे हैं: सब कुछ सुपरक्लास कर सकता है, एक सबक्लास ऐसा करने में सक्षम होना चाहिए। सुपरक्लास किसी भी प्रकार के नियम डीटीओ को स्वीकार करने की विधि घोषित करता है। लेकिन आपके उप-वर्ग में, आप केवल मूल्यांकन मूल्यांकन नियमों के उदाहरण स्वीकार करते हैं। यदि आप निम्नलिखित करते हैं तो क्या होगा? तो यह अनुबंध RuleDTO द्वारा परिभाषित पूरा करना चाहिए

RuleDTO rule = new EvaluationRuleDTO(); 
rule.createRowToBeCloned(new RuleDTO()); 

एक EvaluationRuleDTO, एक RuleDTO है।

सबक्लास में विधि नियम डीटीओ के बजाय मूल्यांकन मूल्यांकन नियम का एक उदाहरण वापस कर सकती है, हालांकि अनुबंध एक नियम डीटीओ वापस करने के लिए है, और मूल्यांकन RuleDTO एक नियम डीटीओ है।

+0

उदाहरण समझ में आता है, धन्यवाद – DJ180

+0

विस्तृत उत्तर मिला [यहां] (http://stackoverflow.com/a/9421315/1276636) – Sufian

+0

वही था जो मैं ढूंढ रहा था। धन्यवाद! –

4

यह इसलिए क्योंकि जब आप एक विधि को ओवरराइड, आप टाइप एक ही प्रकार या एक अधिक सामान्य (व्यापक) टाइप करें, कभी नहीं एक संकरा प्रकार पैरामीटर के रूप में उपयोग करना आवश्यक है।

बस इसके बारे में सोचें। यदि आप एक संक्षिप्त प्रकार का उपयोग करके एक विधि को ओवरराइड कर सकते हैं, तो आप बहुरूपता क्षमता को तोड़ देंगे, क्या आप सहमत नहीं हैं? तो, ऐसा करने से, आप Liskov Substitution Principle तोड़ देंगे क्योंकि जेबी निजेट ने अपने जवाब में कहा था।

+1

अपने जवाब से हवाला देते हुए कहा कि "आप पैरामीटर के रूप में उपयोग करना चाहिए टाइप एक ही प्रकार या एक अधिक सामान्य (व्यापक) प्रकार, कभी नहीं एक संकरा प्रकार", यह नहीं है जावा पर लागू करें। हालांकि यह Liskov सिद्धांत परिप्रेक्ष्य से सच है, विधि पैरामीटर प्रकार जावा में invariant होना चाहिए। – karakays

0

जावा 1.5 co-variant return प्रकार है जो कारण है कि यह वैध है

उपवर्ग विधि की वापसी प्रकार आर 2 सुपर क्लास विधि की वापसी प्रकार आर 1 से अलग हो सकता है, लेकिन आर 2 आर 1 के एक उप-प्रकार होना चाहिए। यानी, सबक्लास वापस लौटा सकता है सुपरक्लास रिटर्न प्रकार का उप प्रकार हो सकता है।

4

जावा ओवरराइड के लिए रिटर्न प्रकार कॉन्वर्सिस की अनुमति देता है, ताकि आप अधिक व्युत्पन्न प्रकार के रूप में ओवरराइड के रिटर्न प्रकार को निर्दिष्ट कर सकें। हालांकि, जावा ओवरराइड के लिए पैरामीटर प्रकार covariance की अनुमति नहीं देता है।

पूर्व सुरक्षित होने का कारण यह है कि आपके द्वारा लौटाई जाने वाली वस्तु कम से कम व्युत्पन्न प्रकार की कार्यक्षमता होगी, इसलिए उस तथ्य पर निर्भर ग्राहक अभी भी लौटे ऑब्जेक्ट का सही उपयोग करने में सक्षम होगा।

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

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

0

प्रारंभिक जावा में जो मामला नहीं था, लेकिन यह जावा 5.0 में बदला गया था।

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

स्रोत: http://www.java-tips.org/java-se-tips/java.lang/covariant-return-types.html

इसका मतलब है कि अधिभावी तरीकों की वापसी प्रकार ओवरराइड विधि की वापसी प्रकार के उपप्रकार हो जाएगा।

class A { 
    A foo(A a) { 
     return new A(); 
    } 
} 

class B extends A { 
    @Override 
    // Returning a subtype in the overriding method is fine, 
    // but using a subtype in the argument list is NOT fine! 
    B foo(B b) { 
     b.bar(); 
     return new B(); 
    } 
    void bar() { 
     // B specific method! 
    } 
} 

हाँ ठीक है, बी एक एक है, लेकिन अगर किसी को करता है कि क्या होता है:

0

कृपया निम्नलिखित कोड को देखने के

B b = new B(); 
b.foo(new A()); 

एक एक बार विधि नहीं है .. यह यही कारण है कि बहस ओवरराइड की विधि में तर्क के प्रकार का एक उप प्रकार नहीं हो सकता है।

ओवरराइडिंग विधि में रिटर्निंग ए या बी ठीक है। निम्नलिखित स्निपेट संकलन और ठीक चलेगा ..

class A { 
    A foo(A a) { 
     return new B(); // B IS AN A so I can return B! 
    } 
} 

class B extends A { 
    @Override 
    B foo(A b) { 
     return new B(); // Overridden method returns A and 
         // B IS AN A so I can return B! 
    } 

    public static void main(String[] args) { 
     A b = new B(); 
     final A foo = b.foo(new B()); 
     // I can even cast foo to B! 
     B cast = (B) foo; 
    } 
} 
संबंधित मुद्दे