2012-11-27 39 views
9

के माध्यम से एक्सेस किए गए सबक्लास में जावा स्थैतिक सदस्य यह एक नए सवाल की तरह प्रतीत होता है, लेकिन पिछली बार जब मैंने जावा के साथ काम किया था, तो भाषा में जेनेरिक नहीं थे।एक सामान्य माता-पिता

public abstract class AbstractBase { .... } 
public class ConcreateSubA extends AbstractBase { .... } 
public class ConcreateSubB extends AbstractBase { .... } 
... 
public class ConcreateSubZZ9PluralZAlpha extends AbstractBase { .... } 
... 

मैं कुछ विरासत कोड को साफ करने के कोशिश कर रहा हूँ, और वहाँ एक जगह है जहाँ दोहराव दोहराव की एक टन सब में बाहर कारक हो सकता है: मैं एक वर्ग पदानुक्रम है (नाम के रूप में संभव के रूप में सामान्यीकृत होने के लिए परिवर्तित) जेनेरिक के माध्यम से एक एकल दिनचर्या। (मैं जेनरिक में सोच रहा हूँ, क्योंकि जब इस दिनचर्या कहा जाता है, यह ठोस वर्ग का केवल एक पर काम करने की जरूरत है।)

दिनचर्या दिखता

public <Thing extends AbstractBase> void someFunc() 
{ 
    another_function_call (Thing.concreteSpecialToken); 
    // could also be 
    // another_function_call (Thing.concreteSpecialToken()); 
    // if methods are more feasible than fields 

    // Cannot use 
    // another_function_call (Thing().concreteSpecialToken()); 
    // because creating instances of these types is a Major Operation[tm] 
} 

की तरह मैं एक असंख्य लाइनों के बारे में बाहर जा रहा हूँ , लेकिन यह महत्वपूर्ण हिस्सा है: someFunc() टाइप पैरामीट्रिक है (यह वास्तव में तर्क लेता है लेकिन उनमें से कोई भी चीजें नहीं हैं इसलिए कोई अनुमान नहीं है)। आखिरकार मुझे एक विशेष टोकन लाने की जरूरत है और यह वह जगह है जहां मुझे अस्पष्ट हो रहा है।

टोकन प्रत्येक ठोस वर्ग के लिए विशाल-गधे अद्वितीय तार हैं। वे कक्षा-आधारित हैं, उदाहरण-आधारित नहीं। प्रत्येक टोकक्लास में वास्तविक टोकन मान को private static final फ़ील्ड के रूप में घोषित किया जाता है।

इसलिए मुझे बेस क्लास के सार्वजनिक तरीकों/फ़ील्ड (अंत में) उप-वर्ग के निजी स्थैतिक क्षेत्र में जाने की आवश्यकता है। जाहिर है, मैं बेस में abstract static विधि घोषित नहीं कर सकता, क्योंकि इसका कोई मतलब नहीं है। यदि डेटा आवृत्ति आधारित था, तो यह बेस क्लास में एक पॉलिमॉर्फिक गेटर के साथ छोटा होगा, लेकिन सबक्लास सामान स्थिर है।

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

+2

'ZZ9PluralZAlpha' के लिए +1 :-) –

उत्तर

7

मैं जावा की सीमाओं या अंतराल को पुल करने की कोशिश कर रहे विशेषज्ञता की कमी के खिलाफ दौड़ रहा हूं।

यह जावा की एक सीमा है, हालांकि काफी उचित एक आईएमओ है। असल में आप अभी भी स्थिर सदस्यों का उपयोग करने की कोशिश कर रहे हैं जैसे कि वे पॉलिमॉर्फिक थे, और यह काम नहीं करेगा - जेनेरिक आपकी मदद नहीं करते हैं।

विकल्प:

  • प्रतिबिंब का प्रयोग करें ... लेकिन भालू मन में है कि प्रकार विलोपन मतलब है कि आप जब तक आप स्पष्ट
  • में इसे पारित आप रखी है, तो Thing के लिए Class पर नहीं मिल सकता हैThing का एक उदाहरण वैसे भी, बस इसे एक सार उदाहरण सदस्य है, जो प्रत्येक कार्यान्वयन में एक स्थिर क्षेत्र का मान देने के लिए होता है बनाने के
  • एक अलग प्रकार hierar बनाएं Chy आप टोकन रखने के लिए के रूप में यह है, एक private static final क्षेत्र चाहते हैं जो उदाहरण के सदस्यों
3

यदि मैं इसे सही ढंग से समझता हूं, तो आपको प्रकार पैरामीटर की ठोस कक्षा की आवश्यकता होती है। ऐसा करने का सामान्य तरीका इस प्रकार आपकी विधि घोषित करना है: public <T extends AbstractBase> void someFunc(Class<T> clazz)

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

कहानी का नैतिक यह है कि जेनेरिक और सांख्यिकी एक साथ अच्छी तरह से नहीं जाते हैं।

2

थोड़ा भद्दा लेकिन अगर someFunc आप प्रतिबिंब इस्तेमाल कर सकते हैं एक Class<Thing> पैरामीटर ले लिया:

public <Thing extends AbstractBase> void someFunc(Class<Thing> clz) { 
    // exception handling omitted 
    Object whatever = clz.getDeclaredMethod("whatever").invoke(null); 

लेकिन आप शायद की तरह

public abstract class AbstractBase { 
    public static class Info { 
    public String getInfo() { 
     return "AbstractBase"; 
    } 
    } 
} 

public class ConcreteSubA extends AbstractBase { 
    public static final Info INFO = new Info() { 
    public String getInfo() { return "ConcreteSubA"; } 
    } 
} 

और नेस्टेड वर्गों का उपयोग करना, कुछ से बहुरूपता सुविधा का लाभ ले सकता है someFuncAbstractBase.Info पैरामीटर लें।

public <Thing extends AbstractBase> someFunc(AbstractBase.Info inf) { 
    String info = inf.getInfo(); 
} 

// call it as 
ConcreteSubB csb = someFunc(ConcreteSubB.INFO); 

विचार पदानुक्रम में प्रत्येक वर्ग एक सिंगलटन उदाहरण Info की अपने पूर्व स्थैतिक डेटा धारण किया है।

+0

यह समस्या है; उस समय कुछ फनक कहा जाता है, अभी तक कोई चीज मौजूद नहीं है। लेकिन मैं प्रतिबिंब पर एक और नजर डालेगा, तो धन्यवाद! –

+0

@TiStrga मैंने एक वैकल्पिक दृष्टिकोण पर थोड़ा सा विस्तार किया है, डेटा को सीधे क्लासिक के बजाए किसी अन्य वर्ग के सिंगलटन इंस्टेंस में डाल दिया है। –

1

का उपयोग करेगा, आप इसे प्रतिबिंब के माध्यम से प्राप्त कर सकते हैं:

public <Thing extends AbstractBase> void someFunc(Class<Thing> clz) 
{ 
    try { 
     Field field = clz.getField("concreteSpecialToken"); 
     field.setAccessible(true); 
     Object concreteSpecialToken = field.get(null); 
     another_function_call (concreteSpecialToken); 
    } catch (IllegalAccessException e) { 
     handle(e); 
    } catch (NoSuchFieldException e) { 
     handle(e); 
    } 
} 

कॉल साइट पर, आप someFunc(ConcreateSubZZ9PluralZAlpha.class) क्या करना है । लेकिन मुझे आश्चर्य है कि क्या आप ऐसा कर सकते हैं, आप someFunc(ConcreateSubZZ9PluralZAlpha.concreteSpecialToken) में पैरामीटर के रूप में टोकन ऑब्जेक्ट को क्यों पास नहीं करते हैं? या शायद टोकन क्लास में someFunc() विधि को भी ले जाएं।