2013-10-23 9 views
6

के लिए अंतिम 1-तत्व सरणी का उपयोग करके मैंने अज्ञात आंतरिक कक्षा से एक चर को बाहरी वर्ग में घोषित करने के लिए इस चाल में ठोकर खाई। यह काम करता है, लेकिन यह एक गंदा हैक की तरह लगता है:गुमनाम आंतरिक कक्षा

private int showDialog() 
{ 
    final int[] myValue = new int[1]; 

    JPanel panel = new JPanel(); 
    final JDialog dialog = new JDialog(mainWindow, "Hit the button", true); 
    dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 

    JButton button = new JButton("Hit me!"); 
    button.addActionListener(new ActionListener() 
    { 
     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      myValue[0] = 42; 
      dialog.setVisible(false); 
     } 
    }); 

    panel.add(button); 
    dialog.add(panel); 
    dialog.pack(); 
    dialog.setVisible(true); 

    return myValue[0]; 
} 

(। हाँ, मैं इस उदाहरण एक साधारण JOptionPane साथ प्रतिस्थापित किया जा सकता है एहसास, लेकिन मेरी वास्तविक संवाद और अधिक जटिल कर रहे हैं) भीतरी समारोह का कहना है कि सभी चर यह final होने के साथ इंटरैक्ट करता है, लेकिन मैं myValue को अंतिम के रूप में घोषित नहीं कर सकता क्योंकि आंतरिक फ़ंक्शन को इसे एक मान असाइन करने की आवश्यकता होती है। इसे 1-तत्व सरणी के रूप में घोषित करने से इस समस्या के आसपास हो जाता है, लेकिन ऐसा लगता है कि यह किसी भी तरह की खराब बात टीएम हो सकती है। मैं सोच रहा हूं कि ए।) यह सामान्य अभ्यास है या बी।) ऐसी कोई गंभीर समस्या है जो ऐसा करने से हो सकती है।

उत्तर

0

गंदे लगते हैं। मैं सचमुच बात नहीं कर सकता कि यह "आम" कैसे है, और मुझे नहीं पता कि आप इसे करकर विश्व विनाश का जोखिम उठा रहे हैं, लेकिन अगर मुझे ऐसा कुछ चाहिए तो मैं बुलेट काटने और लिखना पसंद करूंगा ActionListener को लागू करने के लिए पूर्ण आंतरिक कक्षा (अज्ञात विविधता के बजाय)। इस तरह आप इसे अपने संलग्न वर्ग के क्षेत्रों को प्रभावित कर सकते हैं और आवश्यकतानुसार संलग्न कक्षा में अन्य विधियों को कॉल कर सकते हैं। इस तर्क को पकड़ने के लिए आप वास्तव में क्या कर रहे हैं, इस पर निर्भर करता है कि यह ऑल-इन और सबक्लास Dialog पर जा सकता है।

बोनस के रूप में, गैर-अज्ञात आंतरिक कक्षाएं थोड़ा कम दर्दनाक डिबगिंग करती हैं क्योंकि आपके पास अधिक जानकारीपूर्ण क्लास पहचानकर्ता आपके लिए उपलब्ध हैं।

0

मुझे नहीं लगता कि आपके कोड में कोई समस्या है। मुझे कभी-कभी कुछ इसी तरह का सहारा लेना पड़ता है लेकिन मैं एक विशेष वर्ग का उपयोग करता हूं जो मूल्य को लपेटता है और मैं आंतरिक वर्ग में एक सेटटर कहता हूं लेकिन अंतिम परिणाम समान होता है।

private static class Result{ 
    private Integer value; 

    //getter and setters here 

} 

.... 

final Result result = new Result(); 

... 
new InnerClass(){ 

    void foo(){ 
     result.setValue(42); 
    } 
} 

मुद्दा यह है कि आंतरिक कक्षाएं केवल अंतिम चर का संदर्भ दे सकती हैं क्योंकि उनका स्मृति पता नहीं बदलेगा।

मेरी एकमात्र सलाह आपको int[] का उपयोग मूल्य के रूप में नहीं करना है, लेकिन Integer[] ताकि आप 0 के मान और मूल्य निर्धारित नहीं होने वाले मान (जिसमें मूल्य = शून्य हो) के बीच का अंतर बता सकें।

+0

'int' बनाम 'इंटेगर' चीज़ पर अच्छा बिंदु, लेकिन हकीकत में, कई अलग-अलग प्रकार (आमतौर पर आदिम नहीं) हैं जिन्हें इन संवादों द्वारा उपयोग किया जाता है, इसलिए यह मामूली बात है। इसके अलावा, चूंकि इस मामले में संवाद मोडल है और बटन को मारने के बिना बंद नहीं किया जा सकता है, यह बहुत अधिक गारंटी नहीं है कि कोई समस्या न हो। –

3

यदि कोड सुगम है, जो यह है, तो मैं यह नहीं कहूंगा कि ऐसा करने से यह भयानक है।

एक विकल्प यह है कि जेबटन ने कक्षा में एक समारोह को कॉल किया है जिसमें शोडियल (जिसे अनुमति है) है। फ़ंक्शन एक आवृत्ति चर सेट कर सकता है जिसे वापस कर दिया जाएगा। लेकिन यह मेरे लिए कम सुगम लगता है, इसलिए मैं वास्तव में आपकी विधि पसंद करूंगा।

जब तक कि आप गहराई से पदानुक्रमित यूआई ढांचे नहीं बना रहे हैं, कभी-कभी ये छोटे हैक बिल्कुल ठीक प्रकार की चीज हैं जो आपको करना चाहिए।

आप चिंतित हैं, तो आप मूल रूप से एक ही बात एक निजी भीतरी वर्ग के साथ कर सकते हैं:

private class DialogReturnValue { 
    public int value; 
} 

private int showDialog() 
{ 
    final DialogReturnValue myValue = new DialogReturnValue(); 

    JPanel panel = new JPanel(); 
    final JDialog dialog = new JDialog(mainWindow, "Hit the button", true); 
    dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 

    JButton button = new JButton("Hit me!"); 
    button.addActionListener(new ActionListener() 
    { 
     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      myValue.value = 42; 
      dialog.setVisible(false); 
     } 
    }); 

    panel.add(button); 
    dialog.add(panel); 
    dialog.pack(); 
    dialog.setVisible(true); 

    return myValue.value; 
} 

और वहाँ भी है (अच्छी तरह से "सही" दृष्टिकोण हो सकता है) को देखने के लिए ActionListeners।

+0

यदि यह केवल एक था, तो मैं यह कर सकता था, लेकिन दर्जनों संवाद हैं, जिनमें से प्रत्येक पर विभिन्न प्रकार के नियंत्रण होते हैं और उन्हें किस चीज तक पहुंचने की आवश्यकता होती है, इसके लिए अलग-अलग आवश्यकताएं होती हैं। (संवाद विधियां स्वयं वास्तव में अधिकतर 'शून्य' रिटर्न प्रकार हैं।) मुझे उन सभी चीजों को कवर करने के लिए उन आंतरिक कक्षाओं को बनाना होगा जो मुझे चाहिए। मेरी वर्तमान विधि को कम से कम कोड की आवश्यकता होती है। बस यह सुनिश्चित करना चाहता था कि यह कुछ मामलों में टूट नहीं जाएगा। (उदा। क्या यह थ्रेड-सुरक्षित है? सामान्य रूप से एक्शनलिस्टेनर्स कुछ बहु-थ्रेडिंग मुद्दों को लाते हैं।) –

+0

'actionPerformed' नहीं है जिसे बटन दबाया जाता है या कुछ कहा जाता है? मैं नहीं देखता कि 'showDialog' रिटर्न से पहले बटन दबाया जाएगा। – newacct

+0

जैसा कि मैं इसे समझता हूं (और मैं यहां बिल्कुल सही नहीं हो सकता), JDialog को बनाने और दिखाने का कारण थ्रेड को मूल रूप से 'dialog.setVisible (true) 'लाइन पर लॉक कर देता है जब तक कि जेडियलॉग बंद नहीं हो जाता है, जो इस मामले में केवल तब होता है जब बटन दबाया जाता है। मैं निश्चित रूप से जानता हूं कि यह ठीक काम करता है - 'showDialog()' विधि को कॉल करने वाला थ्रेड तब तक चलना बंद कर देता है जब तक संवाद दिखाई दे। –

1

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

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