मुझे जावा स्विंग क्लास का विस्तार कब करना चाहिए?


35

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

मैं यह समझने पर सवाल कर रहा हूं कि मेरे जावा प्रोफेसर ने हमें क्या करने की सिफारिश की है। उन्होंने सिफारिश की है कि एक JSwingआवेदन के लिए हम कक्षा में निर्माण कर रहे हैं

सभी JSwingवर्गों ( JFrameऔर JButton, JTextBoxआदि) को अलग-अलग कस्टम वर्गों में विस्तारित करना चाहिए और उन में GUI संबंधित अनुकूलन निर्दिष्ट करना चाहिए (जैसे घटक आकार, घटक लेबल, आदि)

अब तक बहुत अच्छा है, लेकिन वह आगे सलाह देने के लिए आगे बढ़ता है कि हर JButton का अपना कस्टम विस्तारित वर्ग होना चाहिए, भले ही एकमात्र विशिष्ट कारक उनका लेबल हो।

उदाहरण के लिए यदि GUI में दो बटन ठीक हैं और रद्द करें । उन्होंने कहा कि वे नीचे के रूप में बढ़ाया जाना चाहिए:

class OkayButton extends JButton{
    MainUI mui;
    public OkayButton(MainUI mui) {
        setSize(80,60);
        setText("Okay");
        this.mui = mui;
        mui.add(this);        
    }
}

class CancelButton extends JButton{
    MainUI mui;
    public CancelButton(MainUI mui) {
        setSize(80,60);
        setText("Cancel");
        this.mui = mui;
        mui.add(this);        
    }
}

जैसा कि आप देख सकते हैं कि setTextफ़ंक्शन में एकमात्र अंतर है ।

तो क्या यह मानक अभ्यास है?

Btw, जिस पाठ्यक्रम पर चर्चा की गई, उसे जावा में बेस्ट प्रोग्रामिंग प्रैक्टिस कहा जाता है

[प्रो से जवाब]

इसलिए मैंने प्रोफेसर के साथ समस्या पर चर्चा की और उत्तर में वर्णित सभी बिंदुओं को उठाया।

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

मुझे लगता है कि मुझे लगता है कि कारण है, लेकिन अभी भी यह सिर्फ विरासत का शोषण कर रहा है और कोड को नाजुक बना रहा है।

बाद में, कोई भी डेवलपर गलती से setTextएक Okayबटन पर कॉल कर सकता है और इसे बदल सकता है। उपवर्ग केवल उस मामले में उपद्रव बन जाता है।


3
JButtonअपने विधायक में सार्वजनिक विधियों का विस्तार और कॉल क्यों करें, जब आप JButtonक्लास के बाहर केवल उन्हीं सार्वजनिक तरीकों को बना सकते हैं और कॉल कर सकते हैं ?

17
यदि आप कर सकते हैं तो उस प्रोफेसर से दूर रहें। यह सर्वोत्तम प्रथाओं से काफी दूर है । आप जैसा सचित्र कोड दोहराव एक बहुत बुरा गंध है।
njzk2

7
बस उससे पूछें, यहाँ अपनी प्रेरणा का संचार करने में संकोच न करें।
एलेक्स

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

1
@ एलेक्स मैंने प्रोफेसर के औचित्य के साथ सवाल अपडेट किया है
पारस

जवाबों:


21

यह लिसकोव प्रतिस्थापन सिद्धांत का उल्लंघन करता है क्योंकि OkayButtonकिसी भी स्थान पर प्रतिस्थापित नहीं किया जा सकता Buttonहै जो अपेक्षित है। उदाहरण के लिए, आप अपनी इच्छानुसार किसी भी बटन के लेबल को बदल सकते हैं। लेकिन ऐसा करना OkayButtonअपने आंतरिक आक्रमणकारियों का उल्लंघन करता है।

यह कोड के पुन: उपयोग के लिए विरासत का एक क्लासिक दुरुपयोग है। इसके बजाय एक सहायक विधि का उपयोग करें।

ऐसा नहीं करने का एक और कारण यह है कि यह एक ही बात को प्राप्त करने का एक जटिल तरीका है कि रैखिक कोड होगा।


यह एलएसपी का उल्लंघन नहीं करता है जब तक कि OkayButtonआपके द्वारा सोचा गया अपरिवर्तनीय नहीं है। OkayButtonकिसी भी अतिरिक्त अपरिवर्तनशीलताओं के लिए नहीं दावा कर सकते हैं, यह केवल एक डिफ़ॉल्ट के रूप में लेख पर विचार करें और पूरी तरह से पाठ के लिए संशोधन का समर्थन करने का इरादा हो सकता है। अभी भी एक अच्छा विचार नहीं है, लेकिन उस कारण से नहीं।
HVD

आप इसका उल्लंघन नहीं कर सकते क्योंकि आप कर सकते हैं। यानी, यदि कोई विधि activateButton(Button btn)किसी बटन की अपेक्षा करती है, तो आप उसे आसानी से एक उदाहरण दे सकते हैं OkayButton। सिद्धांत का मतलब यह नहीं है कि इसमें ठीक वैसी ही कार्यक्षमता होनी चाहिए, क्योंकि इससे वंशानुक्रम बहुत अधिक बेकार हो जाएगा।
सेब'

1
@Sebb लेकिन आप इसे एक फ़ंक्शन के साथ उपयोग नहीं कर सकते setText(button, "x")क्योंकि यह (मान लिया गया) अपरिवर्तनीय है। यह सच है कि यह विशेष रूप से ओकेबटन कोई दिलचस्प आक्रमणकारी नहीं हो सकता है इसलिए मुझे लगता है कि मैंने एक बुरा उदाहरण चुना है। लेकिन यह हो सकता है। उदाहरण के लिए, यदि क्लिक हैंडलर कहता है तो क्या होगा if (myText == "OK") ProcessOK(); else ProcessCancel();? फिर पाठ अपरिवर्तनीय का हिस्सा है।
usr

@usr मैं पाठ के बारे में नहीं सोचता था कि वह आक्रमणकारी का हिस्सा था। आप सही कह रहे हैं, इसका उल्लंघन हुआ है।
सेबब

50

यह हर संभव तरीके से पूरी तरह से भयानक है। पर सबसे , एक कारखाने फ़ंक्शन का उपयोग JButtons निर्माण करने के लिए। यदि आपको कुछ गंभीर विस्तार की आवश्यकता है, तो आपको केवल उनसे विरासत में प्राप्त करना चाहिए।


20
+1। अधिक संदर्भ के लिए, AbstractButton के स्विंग क्लास पदानुक्रम को देखें । फिर JToggleButton के पदानुक्रम को देखेंविभिन्न प्रकार के बटन की अवधारणा के लिए वंशानुक्रम का उपयोग किया जाता है । लेकिन इसका उपयोग व्यावसायिक अवधारणाओं ( हां, नहीं, जारी रखें, रद्द करें ... ) में अंतर करने के लिए किया जाता है
लाईव

2
@Laiv: यहां तक कि, के लिए अलग-अलग प्रकार के होने जैसे JButton, JCheckBox, JRadioButton, बस डेवलपर्स अन्य उपकरणकिटें, सादे AWT, जहां इस तरह के प्रकार के मानक हैं की तरह से परिचित होने के लिए एक रियायत है। सिद्धांत रूप में, वे सभी एक ही बटन वर्ग द्वारा नियंत्रित किए जा सकते हैं। यह मॉडल और यूआई प्रतिनिधि का संयोजन है जो वास्तविक अंतर बनाता है।
होल्गर

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

12

यह स्विंग कोड लिखने का एक बहुत ही गैर-मानक तरीका है। आमतौर पर, आप केवल स्विंगिंग यूआई घटकों, ज्यादातर सामान्यतः JFrame (चाइल्ड विंडो और इवेंट हैंडलर सेट करने के लिए) के उपवर्ग बनाते हैं, लेकिन यहां तक ​​कि सबक्लासिंग अनावश्यक और कई लोगों द्वारा हतोत्साहित किया जाता है। बटन और इतने पर पाठ के अनुकूलन प्रदान करना आमतौर पर AbstractAction वर्ग (या यह प्रदान करता है एक्शन इंटरफ़ेस ) का विस्तार करके किया जाता है । यह पाठ, आइकन और अन्य आवश्यक दृश्य अनुकूलन प्रदान कर सकता है और उन वास्तविक कोड को लिंक कर सकता है जो वे प्रतिनिधित्व करते हैं। आपके द्वारा दिखाए गए उदाहरणों की तुलना में UI कोड लिखने का यह एक बेहतर तरीका है।

(वैसे, Google विद्वान ने आपके द्वारा उद्धृत किए गए पेपर के बारे में कभी नहीं सुना है - क्या आपके पास अधिक सटीक संदर्भ है?)


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

@COMEFROM मैं पूरे स्विंग ट्यूटोरियल को नहीं पढ़ने के लिए स्वीकार करूंगा, इसलिए शायद मैं इस शैली का उपयोग करने से चूक गया हूं, लेकिन जिन पृष्ठों को मैंने देखा है, वे आधार वर्गों का उपयोग करते हैं और उपवर्गों का उपयोग नहीं करते हैं, जैसे docs.oracle .com / javase / tutorial / uiswing / Components / button.html
जूल्स

@ जूल्स को भ्रम के बारे में खेद है, मेरा मतलब था कि प्रोफेसर द्वारा पढ़ाए जाने वाले पाठ्यक्रम / पेपर को जावा में सर्वश्रेष्ठ अभ्यास कहा जाता है
पारस

1
आम तौर पर सच है, लेकिन एक अन्य प्रमुख अपवाद है - JPanel। यह वास्तव में उपवर्ग के लिए अधिक उपयोगी है JFrame, क्योंकि एक पैनल सिर्फ एक सार कंटेनर है।
Ordous

10

IMHO, जावा में बेस्ट प्रोग्रामिंग प्रैक्टिस को जोशुआ बलोच की पुस्तक "इफेक्टिव जावा" द्वारा परिभाषित किया गया है। यह बहुत अच्छा है कि आपका शिक्षक आपको OOP अभ्यास दे रहा है और प्रोग्रामिंग के अन्य लोगों की शैलियों को पढ़ना और लिखना सीखना महत्वपूर्ण है। लेकिन जोश बलोच की पुस्तक के बाहर, सर्वोत्तम प्रथाओं के बारे में राय काफी अलग-अलग है।

यदि आप इस वर्ग का विस्तार करने जा रहे हैं, तो आप विरासत का लाभ भी उठा सकते हैं। सामान्य कोड का प्रबंधन करने के लिए MyButton वर्ग बनाएं और इसे चर भागों के लिए उप-वर्ग बनाएं:

class MyButton extends JButton{
    protected final MainUI mui;
    public MyButton(MainUI mui, String text) {
        setSize(80,60);
        setText(text);
        this.mui = mui;
        mui.add(this);        
    }
}

class OkayButton extends MyButton{
    public OkayButton(MainUI mui) {
        super(mui, "Okay");
    }
}

class CancelButton extends MyButton{
    public CancelButton(MainUI mui) {
        super(mui, "Cancel");
    }
}

यह एक अच्छा विचार कब है? जब आप अपने द्वारा बनाए गए प्रकारों का उपयोग करते हैं! उदाहरण के लिए, यदि आपके पास पॉप-अप विंडो बनाने के लिए एक फ़ंक्शन है और हस्ताक्षर है:

public void showPopUp(String text, JButton ok, JButton cancel)

उन प्रकारों को आपने अभी बनाया है जो कोई भी अच्छा नहीं कर रहे हैं। परंतु:

public void showPopUp(String text, OkButton ok, CancelButton cancel)

अब आपने कुछ उपयोगी बनाया है।

  1. संकलक सत्यापित करता है कि शोपॉप एक ऑकबटन और एक कैंसल बॉटन लेता है। कोड पढ़ने वाला कोई व्यक्ति जानता है कि इस फ़ंक्शन का उपयोग कैसे किया जाता है क्योंकि इस तरह के प्रलेखन का संकलन-समय त्रुटि का कारण होगा यदि यह पुराना हो जाता है। यह एक MAJOR लाभ है। प्रकार सुरक्षा के लाभों के 1 या 2 अनुभवजन्य अध्ययनों में पाया गया कि मानव कोड समझ केवल मात्रात्मक लाभ था।

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

  3. फ़ंक्शन का पहला रूप अधिक लचीला है क्योंकि यह किसी भी दो बटन को प्रदर्शित करेगा। कभी-कभी यह विवश करने से बेहतर है कि वह किस प्रकार के बटन लेगा। बस याद रखें कि आपको किसी भी परिस्थिति में किसी भी बटन के कार्य का परीक्षण करना होगा - यदि यह केवल तभी काम करता है जब आप इसे सही तरह से बटन पास करते हैं, तो आप किसी को भी एहसान नहीं कर सकते हैं कि यह किसी भी तरह का बटन लेगा।

ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के साथ समस्या यह है कि यह घोड़े के सामने गाड़ी डालता है। आपको यह जानने के लिए पहले फ़ंक्शन लिखना होगा कि हस्ताक्षर क्या है, यह जानने के लिए कि क्या इसके लिए प्रकार बनाना उचित है। लेकिन जावा में, आपको पहले अपने प्रकार बनाने की आवश्यकता है ताकि आप फ़ंक्शन हस्ताक्षर लिख सकें।

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

मैं अभी भी बड़ी परियोजनाओं के लिए स्थिर प्रकारों का प्रशंसक हूं और अब कुछ कार्यात्मक उपयोगिताओं का उपयोग करता हूं जो मुझे पहले कार्यों को लिखने और मेरे प्रकारों को बाद में जावा में नाम देने की अनुमति देता है । सिर्फ एक विचार।

PS मैंने muiपॉइंटर को अंतिम बना दिया है - इसे बदलने योग्य बनाने की आवश्यकता नहीं है।


6
आपके 3 बिंदुओं में से, 1 और 3 को सामान्य जेबटन और उचित इनपुट पैरामीटर नामकरण योजना से नियंत्रित किया जा सकता है। बिंदु 2 वास्तव में एक नकारात्मक पक्ष यह है कि यह आपके कोड को अधिक कसकर-युग्मित करता है: क्या होगा यदि आप चाहते हैं कि बटन क्रम उलट हो जाए? क्या होगा यदि, OK / रद्द करें बटन के बजाय, आप Yes / No बटन का उपयोग करना चाहते हैं? क्या आप एक पूरी तरह से नया शोपॉप तरीका बनाएंगे जो एक यसबटन और एक नोबूटन लेता है? यदि आप केवल डिफ़ॉल्ट JButtons का उपयोग करते हैं, तो आपको पहले अपने प्रकार बनाने की आवश्यकता नहीं है क्योंकि वे पहले से मौजूद हैं।
नजला

@NateKerkhofs ने जो कहा, उसे बढ़ाते हुए, एक आधुनिक IDE आपको औपचारिक तर्क नाम दिखाएगा, जबकि आप वास्तविक अभिव्यक्तियों में टाइप कर रहे हैं।
सोलोमन स्लो

8

मैं शर्त लगाने के लिए तैयार हूँ कि आपका शिक्षक वास्तव में यह नहीं मानता है कि आपको इसका उपयोग करने के लिए हमेशा एक स्विंग घटक का विस्तार करना चाहिए। मुझे यकीन है कि वे इसे केवल उदाहरण के रूप में उपयोग कर रहे हैं ताकि आप कक्षाओं का अभ्यास करने के लिए मजबूर कर सकें। मैं अभी तक वास्तविक दुनिया की सर्वोत्तम प्रथाओं के बारे में बहुत अधिक चिंता नहीं करूँगा।

कहा जा रहा है, वास्तविक दुनिया में हम विरासत पर रचना का पक्ष लेते हैं ।

आपका "केवल एक वर्ग का विस्तार होना चाहिए यदि एक आईएस-ए संबंध मौजूद है" अधूरा है। इसे "... के साथ समाप्त होना चाहिए और हमें बड़े बोल्ड अक्षरों में वर्ग के डिफ़ॉल्ट व्यवहार को बदलने की आवश्यकता है ।"

आपके उदाहरण उस मानदंड के अनुकूल नहीं हैं। आपको केवल इसका पाठ सेट करने के extendलिए JButtonकक्षा में नहीं जाना है। आपको केवल घटकों को जोड़ने के extendलिए JFrameकक्षा में नहीं जाना है। आप इन चीजों को उनके डिफ़ॉल्ट कार्यान्वयन का उपयोग करके ठीक कर सकते हैं, इसलिए विरासत को जोड़ना सिर्फ अनावश्यक जटिलताओं को जोड़ना है।

अगर मैं एक वर्ग को देखता हूं कि extendsदूसरी कक्षा, तो मुझे आश्चर्य होगा कि वह कक्षा क्या बदल रही है । यदि आप कुछ भी नहीं बदल रहे हैं, तो मुझे कक्षा के माध्यम से बिल्कुल न देखें।

अपने प्रश्न पर वापस जाएं: आपको जावा क्लास का विस्तार कब करना चाहिए? जब आपके पास एक वर्ग का विस्तार करने के लिए वास्तव में, वास्तव में, वास्तव में अच्छा कारण है।

यहां एक विशिष्ट उदाहरण है: कस्टम पेंटिंग करने का एक तरीका (एक गेम या एनीमेशन के लिए, या सिर्फ एक कस्टम घटक के लिए) JPanelकक्षा का विस्तार करके है । (अधिक है कि के बारे में जानकारी यहाँ ।) आप का विस्तार JPanelक्योंकि आप की जरूरत वर्ग को ओवरराइडpaintComponent() समारोह। आप वास्तव में ऐसा करके कक्षा के व्यवहार को बदल रहे हैं । आप डिफ़ॉल्ट JPanelकार्यान्वयन के साथ कस्टम पेंटिंग नहीं कर सकते ।

लेकिन जैसा कि मैंने कहा, आपका शिक्षक शायद इन उदाहरणों को बहाने के रूप में इस्तेमाल कर रहा है ताकि आप कक्षाओं को बढ़ाने का अभ्यास कर सकें।


1
ओह रुको, आप एक Borderपेंट सेट कर सकते हैं अतिरिक्त सजावट। या एक बनाने JLabelऔर Iconइसे करने के लिए एक कस्टम कार्यान्वयन पास । JPanelपेंटिंग (और JPanelइसके बजाय क्यों JComponent) के लिए उपवर्ग करना आवश्यक नहीं है ।
होल्गर

1
मुझे लगता है कि आपके पास यहां सही विचार है, लेकिन शायद बेहतर उदाहरण चुन सकते हैं।

1
लेकिन मैं दोहराना चाहता हूं कि आपका उत्तर सही है और आप अच्छे अंक बनाते हैं । मुझे लगता है कि विशिष्ट उदाहरण और ट्यूटोरियल इसे कमजोर रूप से समर्थन करते हैं।

1
@ केविनवॉर्कमैन मुझे स्विंग के खेल के विकास के बारे में नहीं पता है, लेकिन मैंने स्विंग में कुछ कस्टम यूआई किए हैं और "स्विंगिंग कक्षाओं का विस्तार नहीं किया है, इसलिए घटकों और रेंडरर्स को कॉन्फ़िगरेशन के माध्यम से तार करना आसान है" वहां काफी मानक है।

1
"मुझे यकीन है कि वे इसे केवल एक उदाहरण के रूप में उपयोग कर रहे हैं ..." मेरे प्रमुख पेशाब में से एक! प्रशिक्षकों जो सिखाने कैसे एक्स करने के लिए की बुरी तरह विक्षिप्त उदाहरणों का उपयोग क्यों एक्स करने के लिए
सोलोमन धीरे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.