2012-10-29 30 views
5

जब आप एक धाराप्रवाह दृष्टिकोण आप इस परिदृश्य पर हो सकता है रोजगार:जावा - घटना वर्ग 'प्रकार, वापस जाने के लिए सुविज्ञ विधि वापसी प्रकार पारंपरिक रूप से प्राप्त नहीं माता पिता की

public class Foo<T extends a>{ 

    public Foo<T> someMethod(){ 
      System.out.println("foo"); 
      return this; 
    } 

} 


public class Bar<T extends b> extends Foo<T> { 

     public Bar<T> barMethod(){ 

      System.out.println("bar"); 
      return this; 
     } 

} 


public class a{} 
public class b extends a{} 

एक धाराप्रवाह इंटरफ़ेस का एक शक्ति है कि आप श्रृंखला कर सकते है विधि आमंत्रण, लेकिन जब बार someMethod() विरासत में मिला है, वापसी प्रकार फू बार जो निम्नलिखित श्रृंखला टूट जाएगा नहीं है:

new Bar<b>().someMethod().barMethod(); 

एक जवाब हर विरासत में मिला विधि के लिए @Overrides जोड़ने के लिए हो सकता है, इस तरह के बार है कि अतिरिक्त विधि:

@Override 
public Bar<T> someMethod(){ 
      System.out.println("foo"); 
      return this; 
    } 

लेकिन बड़ी कक्षाओं में, और विस्तारित वर्ग पदानुक्रमों में यह निश्चित रूप से अनावश्यकता की गड़बड़ी साबित कर सकता है ?! क्या धाराप्रवाह विधियों को देने के लिए कोई उचित रिटर्न प्रकार है जिससे प्रत्येक वर्ग जो इसे प्राप्त करता है, उसके विशिष्ट प्रकार की वस्तु को वापस कर देगा (ताकि हम बिना किसी श्रृंखला के चेन विधियां कर सकें)?

मैंने कोशिश की:

 public <U extends Foo<T>> U someMethod(){ 
      System.out.println("foo"); 
      return this; 
    } 
अफसोस करने के लिए

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

इस परिदृश्य में आप जो भी सहायता प्रदान कर सकते हैं, उसके लिए धन्यवाद।

उत्तर

5

आप इस तरह यह कर सकते हैं, यदि आप एक अनियंत्रित डाली कोई आपत्ति नहीं है:

public class Foo<T, F extends Foo<T, F>> { 
    public F someMethod() { 
    System.out.println("foo"); 
    return (F) this; // <--- That's the unchecked cast! Tucked safely away. 
    } 
    public static void main(String[] args) { 
    new Bar<String>().someMethod().barMethod(); 
    } 
} 

class Bar<T> extends Foo<T, Bar<T>> { 
    public Bar<T> barMethod() { 
    System.out.println("bar"); 
    return this; 
    } 
} 

व्यक्तिगत रूप से, मैं अनियंत्रित कलाकारों को निष्क्रिय पूरी परियोजना के लिए वैश्विक स्तर पर चेतावनी।

+0

लेकिन अभी भी एक 'कास्टिंग' है, जो ओपी नहीं चाहता है। मुझे नहीं पता क्यों। उम्म। लेकिन यह कास्टिंग बेहतर है। यह एक ही स्थान पर है। तो, ओपी इसके साथ ठीक होना चाहिए। अन्य भगवान उसे मदद करते हैं। ;) –

+1

@ रोहितजैन टिप्पणी देखें मैंने उपरोक्त उत्तर पर किया है: यह एक उपयोगिता की बात है, जो इसे अपने प्रोजेक्ट में शामिल करने के लिए क्लाइंट के लिए उपयोग करने के लिए एक बहुत ही सरल lib बनाने की कोशिश कर रहा है। हालांकि मार्को टॉपोलनिक का समाधान दिलचस्प है, और कुछ ऐसा जो मैंने नहीं सोचा था। ऐसा लगता है कि कुछ विवरणों के कारण अपरिहार्य हैं? – ComethTheNerd

+0

@MarkoTopolnik। हाँ, यही कारण है कि मेरी टिप्पणी के अंत में, मैंने कहा कि यह एक बेहतर जगह है, क्योंकि यह एक ही स्थान पर है।:) –

1

आप क्या कर सकते हैं barMethod विधि सार परिभाषित करें ताकि अब आप इसे Foo प्रकार पर कॉल कर सकें।

public abstract class Foo<T extends a> { 

    public Foo<T> someMethod() { 
     System.out.println("foo"); 
     return this; 
    } 

    public abstract Foo<T> barMethod(); 
} 

अब आप आसानी से कॉल कर सकते हैं

new Bar<b>().someMethod().barMethod(); 
+0

इस दृष्टिकोण के साथ समस्या यह है कि यह हमें सीधे फू को तुरंत चालू करने से रोकता है, जिसे मुझे अभी भी करने में सक्षम होना चाहिए। – ComethTheNerd

+0

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

+0

फिर आपको इसे कास्ट करना होगा। –