क्या "स्थिर इंटरफ़ेस" एक अच्छा अभ्यास है?


13

मैंने अभी हाल ही में देखा है कि इंटरफेस में स्टेटिक तरीके होने का विकल्प है। इंटरफ़ेस के स्थिर क्षेत्रों के साथ भी, एक दिलचस्प व्यवहार है: ये विरासत में नहीं मिले हैं।

मैं अनिश्चित हूं कि इसे लागू करने वाले वास्तविक इंटरफेस में कोई उपयोगी है। हालांकि, यह प्रोग्रामर को ऐसे इंटरफेस बनाने में सक्षम बनाता है जो स्थिर सामान के लिए सिर्फ लिफाफे हैं, जैसे कि उपयोगिता वर्ग हैं।

एक सरल उदाहरण वैश्विक स्थिरांक के लिए सिर्फ एक लिफाफा है। एक वर्ग की तुलना में, आप आसानी से लापता बॉयलरप्लेट को नोटिस कर सकते हैं public static finalक्योंकि वे ग्रहण किए जाते हैं (इसे कम क्रिया बनाते हैं)।

public interface Constants {
    String LOG_MESSAGE_FAILURE = "I took an arrow to the knee.";
    int DEFAULT_TIMEOUT_MS = 30;
}

आप कुछ और अधिक जटिल भी बना सकते हैं, जैसे कि कॉन्फिग कुंजियों का छद्म ज्ञान।

public interface ConfigKeys {
    static createValues(ConfigKey<?>... values) {
        return Collections.unmodifiableSet(new HashSet(Arrays.asList(values)));
    }

    static ConfigKey<T> key(Class<T> clazz) {
        return new ConfigKey<>(clazz);
    }

    class ConfigKey<T> {
        private final Class<T> type;
        private ConfigKey(Class<T> type) {
            this.type = type;
        }
        private Class<T> getType() {
            return type;
        }
    }
}

import static ConfigKeys.*;
public interface MyAppConfigKeys {
    ConfigKey<Boolean> TEST_MODE = key(Boolean.class);
    ConfigKey<String> COMPANY_NAME = key(String.class);

    Set<ConfigKey<?>> VALUES = createValues(TEST_MODE, COMPANY_VALUE);

    static values() {
        return VALUES;
    }
}

आप इस तरह से कुछ उपयोगिता "वर्ग" भी बना सकते हैं। हालांकि, उपयोगिताओं में, निजी या संरक्षित सहायक विधियों का उपयोग करना अक्सर उपयोगी होता है, जो कक्षाओं में काफी संभव नहीं है।

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

मुझे आश्चर्य है कि क्या आप इसे एक अच्छा अभ्यास मान सकते हैं। हालांकि कोड शैली और सर्वोत्तम अभ्यास स्वयंसिद्ध नहीं हैं और राय के लिए जगह है, मुझे लगता है कि आम तौर पर राय देने के पीछे वैध कारण हैं।

मुझे इन दोनों जैसे पैटर्न का उपयोग करने के कारणों (नहीं) में अधिक दिलचस्पी है।


ध्यान दें कि मैं उन इंटरफेस को लागू करने का इरादा नहीं करता हूं। वे अपनी स्थिर सामग्री के लिए केवल एक लिफाफा हैं। मैं केवल स्थिरांक या विधियों का उपयोग करने का इरादा रखता हूं और संभवतः स्थैतिक आयात का उपयोग करता हूं।


1
मेरी घुटने की प्रतिक्रिया यह है कि यह केवल खराब चीजों को जन्म दे सकता है। भले ही सार्वजनिक स्थैतिक विधियां अनिवार्य रूप से केवल वैश्विक कार्यों के नाम हैं। ऐसा लगता है कि एक इंटरफ़ेस में किसी भी कार्यान्वयन कोड की अनुमति इसके अनुबंध के खिलाफ अनुपस्थित परिभाषा के रूप में होती है। मैं कहता हूं कि सार कक्षाओं में आंशिक कार्यान्वयन छोड़ दें। मुझे इस पर पढ़ने की आवश्यकता होगी कि यह क्यों जोड़ा गया।
एड्रियन

मुझे अभी जाना है लेकिन मैं कल इस पर कुछ लिखूंगा। इसकी कमी यह है कि पहले एक इंटरफ़ेस का एक स्पष्ट उद्देश्य था जो स्पष्ट रूप से एक AbstractClass के उद्देश्य से अलग किया गया था। अब वे एक तरह से बहुत अधिक ओवरलैप करते हैं जो एक इंटरफेस के भाषा अज्ञेयवाद का उल्लंघन करता है। इसके अतिरिक्त ऐसे मामले भी हैं जहाँ आप कई इंटरफेस से विरासत में नहीं मिल सकते हैं यदि वे डिफ़ॉल्ट तरीकों को लागू करते हैं। तो अब कई इंटरफ़ेस विरासत के अपवाद हैं जहां कोई भी इस्तेमाल नहीं किया गया था। चूंकि जावा ने एक इंटरफेस के आम डिफिनेशन से बहुत अधिक विचलन किया है ...
एड्रियन

यह नए डेवलपर्स को भ्रमित कर सकता है जो मौलिक ओओपी अवधारणाओं जैसे कि इंटरफेसेस, एब्सट्रैक्टस, जब इनहेरिटेंस के बजाय रचना का उपयोग करना चाहते हैं, ... आदि पर उचित हैंडल प्राप्त करने की कोशिश कर रहे हैं।
एड्रियन

एलिस्टर, आप defaultतरीकों के बारे में बात कर रहे हैं । मैं staticतरीकों और क्षेत्रों के बारे में बात कर रहा हूं । वे विरासत में नहीं मिले हैं, इसलिए वे कई विरासत को नहीं तोड़ते हैं।
वलसेक

जवाबों:


1

एक सरल उदाहरण वैश्विक स्थिरांक के लिए सिर्फ एक लिफाफा है।

स्थिरांक पर स्थिरांक लगाना इसलिए कहा जाता है Constant Interface Antipatternक्योंकि स्थिरांक अक्सर एक कार्यान्वयन विवरण मात्र होते हैं। कॉन्स्टेंट इंटरफेस पर विकिपीडिया लेख में और कमियां संक्षेप में प्रस्तुत की गई हैं ।

आप इस तरह से कुछ उपयोगिता "वर्ग" भी बना सकते हैं।

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


1
मुझे नहीं लगता कि यह वास्तव में इस सवाल का जवाब है क्योंकि आप इस नई कार्यक्षमता के बिना इन दोनों चीजों को कर सकते हैं।
एड्रियन

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

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

1

जैसा कि प्रश्न में कहा गया है, इंटरफ़ेस को लागू करने (या त्वरित) के लिए नहीं है। इसलिए हम इसकी तुलना उस वर्ग से कर सकते हैं जिसके पास एक निजी निर्माता है:

  • क्लास super()को कॉल न करने के साथ नहीं बढ़ाया जा सकता है , लेकिन इंटरफ़ेस "कार्यान्वित" किया जा सकता है
  • प्रतिबिंब के बिना वर्ग को तत्काल नहीं किया जा सकता है, जबकि इंटरफ़ेस को आसानी से अनाम वर्ग के रूप में त्वरित रूप से सरल किया जा सकता है: new MyInterface() {};

यह तुलना वर्ग के पक्ष में है क्योंकि यह अधिक नियंत्रण की अनुमति देता है। उस ने कहा, वर्ग का उद्देश्य स्थिर सामान का धारक होना नहीं है, आप उम्मीद करेंगे कि इसके उदाहरण हैं। वैसे, कोई सही विकल्प नहीं है।

"स्थिर इंटरफ़ेस" से विरासत के बारे में एक अजीब बात यह भी है:

  • एक "कार्यान्वयन" वर्ग खेतों को विरासत में मिला है, लेकिन स्थैतिक तरीकों को विरासत में नहीं मिला है
  • एक विस्तृत इंटरफ़ेस को कोई स्थिर सदस्य नहीं मिला है
  • (जबकि एक वर्ग का विस्तार करने वाला वर्ग प्रत्येक गैर-निजी सदस्य को विरासत में देता है ... और चूंकि इसे एक इंटरफ़ेस द्वारा नहीं बढ़ाया जा सकता है, भ्रम की स्थिति कम है)

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


... वैसे भी, एक टीम के कोडिंग कन्वेंशन उन समस्याओं को कवर कर सकते हैं। मेरे लिए, जबकि यह एक प्रोग्रामर के हाथ को कसकर नहीं बाँधता है जैसा कि निजी कंस्ट्रक्टर के साथ एक वर्ग करता है, यह अभी भी बसने वालों की तुलना में कम जोखिम सहन करता है, और बसने वाले अक्सर उपयोग किए जाते हैं।
वलसेक

0

@MarkusPscheidt के रूप में यह विचार अनिवार्य रूप से कॉन्स्टेंट इंटरफ़ेस एंटीपैटर्न का विस्तार है । इस दृष्टिकोण को शुरू में व्यापक रूप से कई असमान वर्गों द्वारा विरासत में दिए गए स्थिरांक के एक सेट की अनुमति देने के लिए व्यापक रूप से उपयोग किया गया था। इसे समाप्त होने का कारण एक एंटीपैटर्न माना जाता था क्योंकि वास्तविक परियोजनाओं में इस दृष्टिकोण का उपयोग करने वाले मुद्दों का सामना करना पड़ा था। मुझे यह सोचने का कोई कारण नहीं दिखता है कि ये समस्याएं केवल स्थिरांक से संबंधित होंगी।

शायद अधिक महत्वपूर्ण बात, वास्तव में ऐसा करने की कोई आवश्यकता नहीं है। इसके बजाय स्थैतिक आयात का उपयोग करें और स्पष्ट करें कि आप क्या आयात कर रहे हैं और कहां से कर रहे हैं।


हां, स्थैतिक आयात स्थिरांक की तुलना में एक बेहतर विचार की तरह लगता है और यह काम करता है जो दोनों वर्गों और इंटरफेस के स्थिर सदस्यों के साथ काम करता है। और यह केवल कक्षा / इंटरफ़ेस के अंदर दिखाई देता है।
वलासेक

@Vlasec सही है, लेकिन इंटरफ़ेस पर ऐसा करने की कोई आवश्यकता नहीं है। एक वर्ग और एक अंतरफलक के साथ ऐसा करने के बीच एकमात्र अंतर यह है कि आप एक से अधिक इंटरफ़ेस से वारिस कर सकते हैं। इस तरह एक उपयोगिता वर्ग के लिए मानक अभ्यास, कंस्ट्रक्टर को तत्काल या विस्तार को रोकने के लिए निजी बनाना है। एक वर्ग पर एक इंटरफ़ेस में ऐसा करने का कोई लाभ नहीं है। यह बस दुरुपयोग के लिए दरवाजा खोलता है।
जिमीजैम

मैं इंटरफेस पर स्थिरांक में मूल्य देख सकता हूं। इंटरफेस कभी-कभी तरीकों को परिभाषित करते हैं और विधियाँ कभी-कभी स्थिरांक को पैरामीटर के रूप में स्वीकार करती हैं। उदाहरण के लिए: interface ColorFilter {Image applyGradient(int colorSpace, int width, byte[] pixels); }। मैं कल्पना कर सकते हैं वहाँ जा रहा है कुछ अलग स्थिरांक RGB, RGBA, CMYK, GREYSCALE, INDEXEDआदि
टिजिन डे विट

@StijndeWitt यह सबसे बुरी बात नहीं होगी, लेकिन आप इस उद्देश्य के लिए इंटरफ़ेस पर एनम या नेस्टेड क्लास का उपयोग कर सकते हैं। असली मुद्दा विरासत के माध्यम से कई वर्गों के दायरे में लाने के लिए इसका उपयोग कर रहा है। स्थैतिक आयात का उपयोग करने के लिए यह दृष्टिकोण स्पष्ट रूप से हीन है।
जिम्मीजैम Jim

0

मैं कहूंगा, यदि आप नई सुविधा का सही तरीके से उपयोग करने में रुचि रखते हैं, तो JDK में कोड पर एक नज़र डालें। इंटरफेस पर डिफ़ॉल्ट तरीके बहुत व्यापक रूप से उपयोग किए जाते हैं और खोजने में आसान होते हैं, लेकिन इंटरफेस पर स्थिर तरीके बहुत ही असामान्य लगते हैं। कुछ उदाहरणों में शामिल java.time.chrono.Chronology, java.util.Comparator, java.util.Map, और काफी कुछ में इंटरफेस java.util.functionऔर java.util.stream

जिन उदाहरणों को मैंने देखा, उनमें से अधिकांश उन एपीआई के उपयोग को शामिल करते हैं जो बहुत सामान्य होने की संभावना है: समय एपीआई में विभिन्न प्रकारों के बीच रूपांतरण, उदाहरण के लिए, तुलना के लिए जो अक्सर फ़ंक्शन या ऑब्जेक्ट में शामिल वस्तुओं के बीच होने की संभावना है। संग्रह। मेरा टेकअवे: यदि आपके एपीआई का एक हिस्सा है जो लचीला होना चाहिए, लेकिन आप कह सकते हैं कि 80% उपयोग के मामले मुट्ठी भर चूक के साथ हैं, तो अपने इंटरफेस पर स्थिर तरीकों का उपयोग करने पर विचार करें। यह देखते हुए कि यह सुविधा जेडीके में कितनी बार इस्तेमाल की जाती है, मैं अपने कोड में इसका उपयोग करते समय बहुत रूढ़िवादी होगा।

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


-1

मुझे आश्चर्य है कि अगर इसका उपयोग न करने के कारण हैं।

कैसे के बारे में, उम, पुराने JVMs के साथ संगतता?

क्या आप इसे सामान्य रूप से एक अच्छा विचार मानते हैं?

नहीं। यह एक पिछड़ा-असंगत परिवर्तन है जो भाषा की अभिव्यंजना में शून्य जोड़ता है। दो अंगूठे नीचे।

क्या कुछ मॉडल स्थितियां हैं जहां आप कक्षाओं की दृढ़ता से अनुशंसा करते हैं?

मैं कार्यान्वयन विवरण शामिल करने के लिए कक्षाओं का उपयोग करने की दृढ़ता से सलाह देता हूं। एक इंटरफ़ेस वास्तव में सिर्फ यह कहने के लिए है कि "यह ऑब्जेक्ट एक्सवाईजेड के संचालन का समर्थन करता है" और इसका किसी भी स्थिर तरीकों से कोई लेना-देना नहीं है जिसे आप इंटरफ़ेस घोषणा में डाल सकते हैं। यह सुविधा बिल्ट-इन मिनी-फ्रिज के साथ एक झुकनेवाला की तरह है। यकीन है कि यह कुछ आला उपयोग है, लेकिन यह मुख्यधारा के लायक होने के लिए पर्याप्त वजन नहीं खींचता है।

अद्यतन: कृपया अधिक डाउनवोट नहीं। स्पष्ट रूप से कुछ लोगों को लगता है कि इंटरफेस में स्थिर तरीके मधुमक्खी के घुटने हैं, और मैं इसके द्वारा कैपिटेटिंग कर रहा हूं। मैं जल्द ही इस उत्तर को हटा दूंगा लेकिन इससे जुड़ी टिप्पणियाँ एक दिलचस्प चर्चा है।


टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
maple_shaft

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