2013-06-25 3 views
13

के साथ जावा कॉपी कन्स्ट्रक्टर शायद इसे दस लाख बार पहले पूछा गया है, लेकिन मुझे एक बाध्य प्रकार पैरामीटर के साथ एक अमूर्त वर्ग पर एक कॉपी कन्स्ट्रक्टर लिखने के आसपास अपने सिर को लपेटने में परेशानी हो रही है। मैं कुछ कोड है कि इस तरह दिखता है:जेनिक्स

public abstract class Superclass<T> { 
    Set<? extends Variable<T>> vars; 

    public abstract Superclass<? extends T> copy(); 

    class Variable<T> { 
     T value; 
    } 
} 

class Foo extends Superclass<Integer> { 
    public Foo copy() { 
     Foo _newFoo = Foo(); 
     Set<FooVariable> _newVars = new HashSet<FooVariable>(); 
     _newVars.addAll(this.vars); 
     _newFoo.vars = _newVars; 
    } 

    class FooVariable extends Variable<Integer> { /* ... */ } 
} 

class Bar extends Superclass<String> { 
    public Bar copy() { 
     Bar _newBar = Bar(); 
     Set<BarVariable> _newVars = new HashSet<BarVariable>(); 
     _newVars.addAll(this.vars); 
     _newBar.vars = _newVars; 
    } 

    class BarVariable extends Variable<String> { /* ... */ } 
} 

के बाद से दोनों Foo और Bar के लिए copy विधि वैरिएबल प्रकार के अलावा एक ही है, मैं में एक ठोस विधि में है कि कोड स्थानांतरित करने में सक्षम होना चाहते हैं superclass। लेकिन मैं समझ नहीं (क) कैसे ठोस public Superclass<? extends T> copy विधि एक Foo उदाहरण लौटने के लिए अगर एक Foo और एक Bar उदाहरण पर बुलाया करता है, तो एक Bar और (ख) FooVariable या के रूप में BarVariable रों साथ vars सेट पॉप्युलेट पर बुलाया उचित।

क्या कोई मेरी मदद कर सकता है और मुझे बता सकता है कि मुझे क्या याद आ रहा है? धन्यवाद।

+2

एक प्रतिलिपि एक वास्तविक निर्माता है जो वर्ग के एक तर्क के रूप में स्वीकार करता है। यह एक प्रतिलिपि विधि है। –

+0

यह इन 'Foo _newFoo = Foo();' और अनुपलब्ध रिटर्न प्रकार के बारे में क्या संकलित त्रुटि देगा? या मैं आपकी मदद के लिए धन्यवाद कुछ अवधारणा – exexzian

उत्तर

0

Variable<T>, U का प्रतिनिधित्व करने के लिए एक दूसरे सामान्य प्रकार पैरामीटर का परिचय दें।

फिर, Foo.FooVariable<T> और Bar.BarVariable<T>U की सीमा को संतुष्ट और copy विधि से लौटाया जा सकता।

संपादित

मैं सुपर क्लास में copy के कार्यान्वयन स्थानांतरित करने के लिए कोड बदल दिया है। यह newInstance विधि (@OndrejBozek द्वारा पहले से पेश किया गया) पर निर्भर करता है।

public abstract class Superclass<T, U extends Variable<T>> { 
    Set<U> vars; 

    class Variable<T> { 
     T value; 
    } 

    public Superclass<T, U> copy() { 
     Superclass<T, U> _newSuperclass = newInstance(); 
     Set<U> _newVars = new HashSet<U>(); 
     _newVars.addAll(vars); 
     _newSuperclass.vars = _newVars; 
     return _newSuperclass; 
    } 

    public abstract Superclass<T, U> newInstance(); 
} 

class Foo extends Superclass<Integer, Foo.FooVariable> { 
    public Foo newInstance() { return new Foo(); } 

    class FooVariable extends Variable<Integer> { /* ... */ } 
} 

class Bar extends Superclass<String, Bar.BarVariable> { 
    public Bar newInstance() { return new Bar(); } 

    class BarVariable extends Variable<String> { /* ... */ } 
} 
+0

धन्यवाद। यद्यपि यह समाधान उस प्रकार की सुरक्षा को मजबूर करता है जिसमें मुझे रूचि है, फिर भी मैंने 'Foo.copy' और' Bar.copy' विधियों में कोड को बहुत अधिक डुप्लिकेट किया है। क्या आप उस कोड को सुपरक्लास में ले जाने के तरीके के बारे में सोच सकते हैं? – jay

+0

@jay, मैंने सुपर कॉपी में 'कॉपी' को स्थानांतरित करने के प्रयास में अपना जवाब संशोधित कर दिया है। – rgettman

2

इस प्रकार के Superclass के बारे में क्या?

public abstract class Superclass<T> { 

    Set<? extends Variable<T>> vars; 

    public Superclass<? extends T> copy() { 
     Superclass<T> _newSuperclass = this.getNewInstance(); 
     Set<Variable<T>> _newVars = new HashSet<Variable<T>>(); 
     _newVars.addAll(this.vars); 
     _newSuperclass.vars = _newVars; 
     return _newSuperclass; 
    } 

    public abstract Superclass<T> getNewInstance(); 

    class Variable<T> { 

     T value; 
    } 
} 

मुद्दा यह है कि तुम सिर्फ निर्माता के बजाय उपवर्गों में getNewInstance() लागू करने की आवश्यकता है।

तो Foo सिर्फ लगेगा चाहते:

class Foo extends Superclass<Integer> { 

    @Override 
    public Superclass<Integer> getNewInstance() { 
     return new Foo(); 
    } 

    class FooVariable extends Variable<Integer> { /* ... */ } 
} 
+0

हां यह संकलित करता है। बस इसे जावा 1.7 के साथ संकलित किया। उस कोड के बारे में क्या गलत होना चाहिए? –

+1

क्षमा करें, मैं गलत सोच रहा था ... – jlordo

+0

मुझे लगता है कि आप '_newSuperClass.vars = _newVars;' – Alex

0

इस कोड को परीक्षण किया गया है, यह चेतावनी के एक जोड़े है, लेकिन यह तुम क्या चाहते है:

public <C extends Superclass<? extends T>> C copy() throws InstantiationException, IllegalAccessException { 
    C result= (C) this.getClass().newInstance(); 
    HashSet newVars= new HashSet(); 
    newVars.addAll(this.vars); 
    result.vars= newVars; 
    return result; 
} 

एक टिप्पणी: यह एक नहीं है प्रतिलिपि निर्माता। यह सिर्फ एक प्रति विधि है। कन्स्ट्रक्टर के पास रिटर्न टाइप नहीं होता है और इसका नाम कक्षा के नाम के बराबर होता है।

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