2010-07-13 12 views
9

मैं की तरह एक अंतरफलक है निम्नलिखित:जावा: आंतरिक enums युक्त इंटरफेस; कार्यान्वयन की कक्षाओं में विस्तार कार्यक्षमता

package example; 
import java.awt.Point; 

public interface Thing { 
    public enum MovingState { 
     MOVING_LEFT, 
     MOVING_UP, 
     MOVING_RIGHT, 
     MOVING_DOWN 
    } 

    public void setNewPosition(MovingState state); 
    public Point getPosition(); 
} 

और एक कार्यान्वयन वर्ग:

package example; 
import java.awt.Point; 

public class ThingImpl implements Thing { 
    public enum MovingState { 
     MOVING_LEFT (-1, 0), 
     MOVING_UP (0, -1), 
     MOVING_RIGHT (1, 0), 
     MOVING_DOWN (0, 1); 

     private int x_move; 
     private int y_move; 

     MovingState(int x, int y) { 
      x_move = x; 
      y_move = y; 
     } 

     public int xMove() { 
      return x_move; 
     } 

     public int yMove() { 
      return y_move; 
     } 
    } 


    private Point position; 

    public void setNewPosition(MovingState state) { 
     position.translate(state.xMove(), state.yMove()); 
    } 

    public Point getPosition() { 
     return position; 
    } 
} 

विचार ThingImpl में MovingStateThing इंटरफ़ेस से MovingState का विस्तार (इस प्रकार है इंटरफ़ेस से MovingState के वास्तविक कार्यान्वयन को अलग करना)।

यह हालांकि काम नहीं करता है - ThingImpl छाया बजाय इसे विस्तार के इंटरफेस में परिभाषा MovingState enum, तो संकलक शिकायत है कि ThingImpl सार नहीं है और में सार विधि setNewPosition (Thing.MovingState) पर हावी नहीं होता चीज़।

क्या मैं ऐसा करने का प्रयास कर रहा हूं जो मैं प्राप्त करने की कोशिश कर रहा हूं? या जावा में बस यह क्षमता नहीं है?

उत्तर

11

क्या तुम सच में क्या करना चाहते हैं अपने "ThingImpl" वर्ग और इस कदम से enum घोषणा को दूर है:

public interface MovingInterface {  
    int xMove(); 
    int yMove(); 
} 

और उसके बाद:

अपने मामले के लिए आप कुछ इस तरह कर सकते हैं चीज इंटरफ़ेस में यह सब (इसके कन्स्ट्रक्टर और गेटर्स सहित)।

याद रखना होगा कि वे छुआ नहीं किया जाना चाहिए enum में अपने खेतों अंतिम बनाओ।

इस फैशन में, थिंग इंटरफ़ेस का उपयोग करने की इच्छा रखने वाले किसी भी चीज को आपके इंटरफ़ेस पर परिभाषित गणना का उपयोग करना चाहिए - आपकी समस्या यह है कि आप इसे प्रभावी रूप से दो बार परिभाषित कर रहे हैं, लेकिन यह या तो इंटरफ़ेस पर होना चाहिए (जो ठीक है केवल इस इंटरफ़ेस के लिए उपयोग किया जाएगा) या एक सार्वजनिक स्तर enum जावा फ़ाइल के रूप में (सार्वजनिक कक्षा के बजाय सार्वजनिक enum का उपयोग कर)। Map.Entry, मेरी राय में, एक बुरा नेस्टेड इंटरफ़ेस क्योंकि अन्य वर्गों के पास नक्शे की बाहरी एक मुख्य/मान जोड़े के लिए उपयोग किया है और है - अगर अन्य की तुलना में अपने इंटरफेस यथोचित इसका इस्तेमाल करने की उम्मीद कर सकता है कुछ आप इसे एक सार्वजनिक enum बनाने चाहते हैं इस प्रकार यह अपने आप ही इंटरफ़ेस होना चाहिए, लेकिन हम इसे साथ रहने के लिए :(

विचार ThingImpl में MovingState बात इंटरफ़ेस से विस्तार MovingState (इस प्रकार इंटरफ़ेस से MovingState के वास्तविक क्रियान्वयन को अलग करने) के लिए है।

मुझे नहीं लगता कि यह वास्तव में आपका विचार है - मुझे लगता है कि थिंग के इंटरफ़ेस पर आपके द्वारा निर्दिष्ट व्यवहार ठीक है, आप वास्तव में मूविंगस्टेट एनम को स्पर्श नहीं करना चाहते हैं ठीक है जैसा कि है। यदि आपको लगता है कि कुछ को मूविंगस्टेट के एक अलग कार्यान्वयन की आवश्यकता है, हालांकि, आप इसे MovingState नामक इंटरफ़ेस को कार्यान्वित कर सकते हैं और इस प्रकार आप अपने enum DefaultMovingState का नाम बदल सकते हैं। यह तुम्हारी पसंद है।

आपका MovingState इंटरफ़ेस बस ही टिककर खेल आप MovingState में उजागर कर रहे हैं अभी के लिए होगा। दो तरीके

-2

आप जो प्रयास कर रहे हैं वह एक एंटीपाटर है। स्थिरांक को एक इंटरफ़ेस में परिभाषित नहीं किया जाना चाहिए।

http://en.wikipedia.org/wiki/Constant_interface

मैं अपने इंटरफेस से बाहर स्थिरांक कदम होगा, या बस उन्हें तरीकों करते हैं और आपका कार्यान्वयन उन तरीकों को लागू करने से उन्हें परिभाषित करते हैं ...

+2

-1 - आप सही नहीं, वह नहीं विरोधी पैटर्न कर रहा है कर रहे हैं। वह जो कर रहा है वह बेवकूफ है, लेकिन यह लगातार इंटरफ़ेस पैटर्न नहीं है क्योंकि उसका इंटरफ़ेस * व्यवहार को परिभाषित करता है *, और निरंतर मान रखने के लिए काम नहीं करता है। इंटरफेस पर स्थिरांक को परिभाषित करना ठीक है IFF का उपयोग इंटरफेस के व्यवहार के साथ किया जाना चाहिए। – MetroidFan2002

+0

हाँ मुझे लगता है कि यह सही है और मैं वोट के लायक हूं। हालांकि, दृष्टिकोण गलत दिशा में एक कदम है और मैं (संभवतः एक अमूर्त वर्ग में डाल दिया) अभी भी अच्छा है ... – hvgotcodes

+0

उन्होंने कहा कि कर सकता है तरीकों में अपने MOVING_LEFT प्रकार स्थिरांक करते समय, के बारे में मेरी सलाह है, लेकिन फिर उसके इंटरफेस लगता है अगर वह वास्तव में अतिरिक्त दिशाओं को जोड़ना चाहता है तो वह भुगतेंगे। बाएं तरफ ऊपर तिरछे कदम के बारे में क्या? यह एक और तरीका है, लेकिन सिर्फ एक अतिरिक्त गणना निरंतर है। आप यहां तक ​​कि अधिक गूढ़ enums भी बना सकते हैं - ऊपर, ऊपर, नीचे ले जाएँ। प्रत्येक को एक अलग विधि के रूप में लागू करने के बाद इंटरफेस गुब्बारा बनाता है। – MetroidFan2002

5

आप एक enum क्योंकि विस्तार नहीं कर सकते यह final है।

आप प्रभावी जावा द्वितीय संस्करण, आइटम 34: इंटरफेस के साथ अनुकरण एक्स्टेंसिबल एनम्स पढ़ना चाह सकते हैं। अनिवार्य रूप से यह enum पर उबलता है कि implements Something

+0

केवल आधे सच के साथ विस्तार नहीं कर सकते हैं। प्रत्येक enum मान एक अज्ञात वर्ग हो सकता है जो आपके enum वर्ग को बढ़ाता है। – josefx

+0

मेरे पास इस पुस्तक तक पहुंच नहीं है, लेकिन नमूना कोड से मैं जो कह सकता हूं, उससे यह आइटम उस चीज़ को शामिल नहीं करता है जिसे मैं प्राप्त करने की कोशिश कर रहा हूं। मद 34 नई स्थिरांक जोड़ने के लिए विस्तार enums कवर करने के लिए लगता है, लेकिन मेरे उद्देश्य केवल सदस्य कार्यों को जोड़ने में है। मेरे बेस क्लास (चीज) में enum सभी आवश्यक स्थिरांक शामिल हैं। कार्यक्षमता वह है जो मैं कार्यान्वयन कक्षा (ThingImpl) में छिपाने की उम्मीद कर रहा था। – MatthewD

+0

@ मैथ्यू: मुझे नहीं लगता कि एक 'enum' कुछ अमूर्त प्रकार को परिभाषित करने के लिए उपयुक्त है; एक 'इंटरफेस' अधिक उपयुक्त है। शायद आपके पास 'moveUp()', 'moveDown()', आदि के साथ 'इंटरफ़ेस ऑर्थोगोनली मोवेबल' हो सकता है, और एक विशेष कार्यान्वयन है जो 'enum' का उपयोग करता है। – polygenelubricants

3

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

मान लें कि आपके पास एक इंटरफेस है जिसमें कई कार्यान्वयन हैं। इंटरफ़ेस में एक विधि एक तर्क के रूप में enum में ले जाती है। आदर्श रूप से आप प्रति कार्यान्वयन मूल्यवान मूल्यों के विशिष्ट सेट रखना चाहते हैं। हालांकि, चूंकि आप enums का विस्तार नहीं कर सकते हैं, इसलिए आप "आधार" enum नहीं बना सकते हैं और उस से विस्तार कर सकते हैं। निष्पक्ष दृष्टिकोण एक "भगवान" enum होगा जो गणना मूल्यों के पूरे सेट को बनाए रखता है। लेकिन एक बेहतर तरीका है। आप मार्कर इंटरफ़ेस के रूप में जाने जाते हैं का उपयोग कर सकते हैं। प्रभावी जावा 2 एड। इसके बारे में भी बात करते हैं। मार्कर इंटरफ़ेस में कोई विधि घोषणा नहीं होगी, लेकिन अंक एक वर्ग को एक निश्चित प्रकार के रूप में चिह्नित किया जाएगा।

तो आप एक मार्कर इंटरफ़ेस को परिभाषित कर सकते हैं और अपने सभी enums उस इंटरफ़ेस को कार्यान्वित कर सकते हैं। यह enum एक्स्टेंसिबल बनाने में संबंध रखता है, क्योंकि यदि आप एक इंटरफ़ेस को परिभाषित करते हैं जो आपके enum का विस्तार करता है, तो आपने स्वचालित रूप से अपने enum को एक निश्चित प्रकार के रूप में चिह्नित किया है।

इस तरह आप अपने विशिष्ट कार्यान्वयन (चिंता का अलगाव) के साथ सभी विशिष्ट गणना मूल्यों को रख सकते हैं।

public enum MovingState implements MovingInterface { 
    MOVING_LEFT (-1, 0), 
    MOVING_UP (0, -1), 
    MOVING_RIGHT (1, 0), 
    MOVING_DOWN (0, 1); 

    private int x_move; 
    private int y_move; 

    MovingState(int x, int y) { 
     x_move = x; 
     y_move = y; 
    } 

    public int xMove() { 
     return x_move; 
    } 

    public int yMove() { 
     return y_move; 
    } 
} 
संबंधित मुद्दे