2015-02-16 7 views
8

नहीं बुलाया जाना चाहिए लागू करने के लिए सबसे अच्छा अभ्यास मैं एक जावा वर्ग एक है जो एक विधि fooएक व्युत्पन्न विधि है कि

abstract class A { 
    abstract void foo(); 
} 

मैं भी की एक व्युत्पन्न वर्ग है है है। MutableA एक सिंगलटन ऑब्जेक्ट है जो इंगित करता है कि कोई अपडेट आवश्यक नहीं है जो कोड प्रवाह का पुन: उपयोग करने के लिए उपयोगी है। foo() को MutableA पर कभी नहीं बुलाया जाना चाहिए।

  1. फेंक असमर्थित अपवाद
  2. कुछ भी नहीं (खाली कार्यान्वयन)
  3. यह एक बुरा डिजाइन क्या इतना कभी है कार्य करें: सबसे अच्छा तरीका है कि प्राप्त करने के लिए क्या है।

क्या कोई मुझे सलाह दे सकता है कि इस मामले में सबसे अच्छा अभ्यास क्या है?

+4

यह वास्तव में 'foo' क्या करना चाहिए के विनिर्देशों पर निर्भर करता है। इनमें से कोई भी विकल्प लागू हो सकता है। – chrylis

+2

आप ऐसा करने पर विचार कर सकते हैं कि अमरूद 'अपरिवर्तनीय * कक्षाएं क्या करती हैं, जो इस तरह के तरीकों को चिह्नित करने के लिए है '@ अस्वीकृत'। यह आपको कॉल करने से नहीं रोकता है, लेकिन कम से कम आपका आईडीई (यदि आप एक का उपयोग करते हैं) तो आपको यह संकेत मिल सकता है कि कुछ बढ़ रहा है, बशर्ते कि आपके पास विशेष रूप से 'MutableA'' का संदर्भ हो। –

+1

यदि आप Google के गुवा से प्रेरणा आकर्षित करना चाहते हैं, तो वे एक अप्रत्याशित संरचना पर एक उत्परिवर्तन संग्रह विधि को कॉल करते हुए 'असमर्थित ऑपरेशन अपवाद' फेंक देते हैं। वे विधि को '@ अस्वीकृत' के रूप में भी चिह्नित करते हैं। –

उत्तर

2

चूंकि आप कहते हैं कि "कोई अपडेट आवश्यक नहीं है", ऐसा लगता है कि एक खाली कार्यान्वयन जाने का तरीका है। क्या होगा अगर मैं करता हूँ:

A someA = createA(); 
someA.foo();   // make sure it's "foo"ed 

अगर मैं वापस मिल एक MutableA या नहीं, इसलिए मैं foo फोन बस सुनिश्चित करने के मैं नहीं जानता होगा।

यदि यह मना एक MutableA पर foo कॉल करने के लिए मैं UnsupportedOperationException के साथ जाने या डिजाइन पर पुनर्विचार करेंगे। शायद आप को AHandler में लपेट सकते हैं, जिसमें यह पता चलता है कि foo को कब और कैसे कॉल किया जाए, उदाहरण के लिए यह लपेटता है।

2

मैं डिजाइन पर पुनर्विचार पर विचार करता हूं।

सुपर क्लास में एक अमूर्त विधि होने का तात्पर्य है कि उप-वर्गों को उस विधि को लागू करना चाहिए। जब तक आप एक बड़े पदानुक्रम रखने की योजना नहीं बनाते हैं, तो आपको इस मामले में पदानुक्रम में फू विधि को कम करने पर विचार करना चाहिए।

यदि आप foo विधियों के स्थान को रखने के इरादे से हैं तो मैं MutableA सार भी बनाउंगा।

+0

से सभी संवेदनशीलताओं को फेंक दिया गया है, मैं सहमत हूं कि पदानुक्रम बदलना चाहिए - शायद एक मध्यवर्ती स्तर पेश किया जाना चाहिए । यदि किसी ऑब्जेक्ट पर कोई विधि उपलब्ध है तो मुझे उम्मीद है कि मैं इसका भी उपयोग कर सकता हूं। –

+0

यह सब निर्भर करता है क्योंकि उपयोग केस खाली कार्यान्वयन के साथ ऐसी विधि को कॉल करने की अनुमति दे सकता है। चूंकि हम विवरण नहीं जानते हैं कि असुर सटीक नहीं हो सकता है – Gaskoin

1

यह इस बात पर निर्भर करता है कि विधि का उपयोग किस प्रकार किया जाता है। आपके द्वारा सूचीबद्ध सभी विकल्प वस्तुतः अच्छे हैं।

अगर आप UnsupportedOperation अपवाद फेंकते हैं तो आप यह कह रहे हैं कि इस विधि का उपयोग नहीं किया जाना चाहिए। अपवाद का उपयोग करना हमेशा "सामान्य" से विचलन का "संदेश" होता है, इसलिए आप A.foo() के मूल कार्यान्वयन के साथ कुछ करने के लिए परिभाषित कर रहे हैं लेकिन आप उपखंड के साथ इस कार्यान्वयन को भी तोड़ रहे हैं।

यदि आप खाली कार्यान्वयन का उपयोग करते हैं तो आप उप-वर्ग को एक हाइपोटेटिकल प्रवाह के अंदर अधिक उपयोग करने योग्य बना रहे हैं, अतीत के साथ तोड़ने के बिना (सुपर क्लास A), ताकि आप जो भी संदर्भ चाहते हैं उसमें सबक्लास का उपयोग करने के बारे में आपको पता न हो ।

अंतिम विश्लेषण में आपने कहा कि MutableA सिंगलटन है, इसलिए मुझे लगता है कि आप इसे एक विशिष्ट संदर्भ में उपयोग करेंगे, इसके बारे में एक विशिष्ट आंख के साथ: इसलिए मैं "अपवाद" समाधान अपनाउंगा।जहां, A प्राप्त बजाय ReadableA उपयोग करते हैं, जब तक आप विशेष रूप से foo() कॉल करना चाहते हैं करना चाहते हैं अपने कोड में

public abstract class ReadableA { 
} 

public abstract class A extends ReadableA{ 
    abstract void foo(); 
} 

public class MutableA extends ReadableA { 
} 

हर जगह:

1

मैं कुछ इस तरह का उपयोग करेंगे। फिर अपने विधि हस्ताक्षर में A डालें। यदि आप MutableA प्राप्त करना चाहते हैं, तो MutableA हस्ताक्षर लिखें।

उदाहरण:

public class UsageOfA { 
    public void bar(ReadableA a) { 
    // Can use both A and MutableA but a.foo() cannot be invoked. 
    } 
    public void bar(A a) { 
    a.foo(); 
    } 
    public void bar(MutableA a) { 
    // a.foo() cannot be invoked. 
    } 
} 
1

मैं UnsupportedOperationException फेंकने लगता है कि यहाँ सही विकल्प है। मान लें कि A का विस्तार करने वाले 3 वर्ग।

class X extends A{ 
//foo allowed here 
} 
class Y extends A{ 
//foo allowed here 
} 
class Z extends A{ 
//foo allowed here 
} 
class MutableA extends A{ 
//foo NOT allowed here 
} 

अब एक डिजाइन दृष्टिकोण से, X,Y,Z and MutableAfoo() के संबंध में एक संगत तरह से व्यवहार करना चाहिए। मैं MutableA foofree बनाने के लिए बस एक और कक्षा पदानुक्रम लाने में हतोत्साहित करूंगा। एक साधारण आत्मा को UnsupportedOperationException फेंक दिया जाएगा और कॉलर को यह पता चलेगा कि विधि कॉलिंग ऑब्जेक्ट द्वारा समर्थित नहीं हो सकती है। एक खाली दूसरी ओर कार्यान्वयन अभी भी मान्य है और स्पष्ट रूप से अच्छी तरह से अनुकूल नहीं है एक डिजाइन परिप्रेक्ष्य से, क्योंकि यह अभी भी बुला वस्तु से एक वैध कॉल है।

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

2

आपको लिविकोव प्रतिस्थापन सिद्धांत पर एक नज़र डालना चाहिए, जो कि अच्छे डिजाइन के मौलिक सोलिड सिद्धांतों में से एक है।

सिद्धांत बताता है कि व्युत्पन्न वस्तुओं को अपने माता-पिता से अलग व्यवहार नहीं करना चाहिए। लिस्कोव सिद्धांत के उल्लंघन के लिए एक आम उदाहरण एक अंडाकार से एक सर्कल का व्युत्पन्न है। जो गणितीय रूप से पूरी तरह समझदार है और ध्वनि को खराब डिजाइन माना जाता है, क्योंकि एक अंडाकार से व्युत्पन्न एक सर्कल (उदाहरण के लिए) अभी भी चौड़ाई और ऊंचाई निर्धारित करने के तरीकों का पर्दाफाश करता है, लेकिन यह कुछ संदर्भों में अजीब व्यवहार करेगा। निम्नलिखित

Something FooBar (Ellipse e) 
{ 
    // do something with e 
} 

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

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