2013-08-09 7 views
10

मुझे आश्चर्य है कि निम्नलिखित करने का कोई तरीका है या नहीं। मेरे पास एक अमूर्त वर्ग है, Shape, और इसके सभी अलग-अलग सबक्लास और मैं क्लोन विधि को ओवरराइड करना चाहता हूं। मैं इस विधि में करना चाहता हूं, वर्तमान में toString() से नया Shape बनाएं। जाहिर है, मैं निम्नलिखित नहीं कर सकता क्योंकि Shape सार है। ऐसा करने का कोई और तरीका है क्योंकि प्रत्येक सबक्लास में क्लोन ओवरराइड करना सिर्फ एक साधारण नाम परिवर्तन के लिए बेकार लगता है।जावा क्लोनिंग सार वस्तुएं

public abstract class Shape { 

    public Shape(String str) { 
     // Create object from string representation 
    } 

    public Shape clone() { 
     // Need new way to do this 
     return new Shape(this.toString()); 
    } 

    public String toString() { 
     // Correctly overriden toString() 
    } 
} 
+1

प्रतिबिंब का उपयोग करें? – johnchen902

उत्तर

5

आप प्रतिबिंब इस्तेमाल करने की कोशिश कर सकते हैं:

public abstract class AClonable implements Cloneable{ 

private String val; 

public AClonable(){ 

} 

public AClonable(String s){ 
    val=s; 
} 

public String toString(){ 
    return val; 
} 

@Override 
public AClonable clone(){ 
    try { 
     System.out.println(getClass().getCanonicalName()); 
     AClonable b= getClass().getDeclaredConstructor(String.class).newInstance(val); 

     return b; 
    } catch (InstantiationException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IllegalArgumentException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (SecurityException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (InvocationTargetException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (NoSuchMethodException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    return null; 
} 

} विधि क्लोन() में

आप getClass फोन()। चूंकि ACloneble ist सार है, वहाँ कॉल कंक्रीट कक्षा में जायेंगे।

public class ClonebaleOne extends AClonable{ 

public ClonebaleOne(){ 
    super(); 
} 

public ClonebaleOne(String s) { 
    super(s); 
    // TODO Auto-generated constructor stub 
} 

}

और

public class ClonebaleTwo extends AClonable{ 

public ClonebaleTwo(){ 
    super(); 
} 

public ClonebaleTwo(String s) { 
    super(s); 
    // TODO Auto-generated constructor stub 
} 

}

और अंत में

public static void main(String[] args){ 
    AClonable one = new ClonebaleOne("One"); 
    AClonable tow= new ClonebaleTwo("Two"); 
    AClonable clone = one.clone(); 
    System.out.println(clone.toString()); 
    clone = tow.clone(); 
    System.out.println(clone.toString()); 

} 

आउटपुट:

)

[संपादित करें] पूरा नहीं करने के लिए;

ClonebaleOne 
    One 
    ClonebaleTwo 
    Two 

लेकिन यह अधिक एक समाधान

[संपादित करें] मेरे दो क्लोन की तुलना में तेजी थे की तुलना में एक हैक है। क्लोन() का एक अन्य इम्प्लांटेशन

@Override 
public AClonable clone(){ 
    try { 
     ByteArrayOutputStream outByte = new ByteArrayOutputStream(); 
     ObjectOutputStream outObj = new ObjectOutputStream(outByte); 
     ByteArrayInputStream inByte; 
     ObjectInputStream inObject; 
     outObj.writeObject(this); 
     outObj.close(); 
     byte[] buffer = outByte.toByteArray(); 
     inByte = new ByteArrayInputStream(buffer); 
     inObject = new ObjectInputStream(inByte); 
     @SuppressWarnings("unchecked") 
     Object deepcopy = inObject.readObject(); 
     inObject.close(); 
     return (AClonable) deepcopy; 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

जब आपका सार वर्ग Serialazable लागू करता है। वहां आप डिस्क पर अपना ऑब्जेक्ट लिखते हैं और डिस्क से मूल्य के साथ एक प्रति बनाते हैं।

+0

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

+0

प्रत्येक उपclass में उन्हें परिभाषित करने के लिए ऑब्जेक्ट उन्मुख तरीके से सबसे अच्छा समाधान है। मैं sanbhat के साथ सहमत हूँ। मुझे डर है कि Serialazable- समाधान सबसे धीमा है और यह एक हैक भी है। –

2

आप गहरी क्लोन abstract वर्ग के नहीं बना सकते क्योंकि वे instantiated नहीं किया जा सकता है। आपको बस इतना कर सकते हैं Object.clone() का उपयोग कर या this

@Override 
public Object clone() throws CloneNotSupportedException { 
    return super.clone(); 
} 

या

@Override 
public Object clone() throws CloneNotSupportedException { 
    return this; 
} 

एक सार वर्ग लौटने एक संदर्भ के रूप में कार्य कर सकते द्वारा उथले क्लोनिंग है, और यह एक उदाहरण तो उथले क्लोनिंग में काम करता है नहीं हो सकता इस मामले

या

एक बेहतर दृष्टिकोण के रूप में, आप कर सकते हैं clone()abstract के रूप में घोषित करने और हालांकि मुझे शक है यह एक अच्छा विचार है यह, कुछ इस

abstract class Shape { 

    private String str; 

    public Shape(String str) { 
     this.str = str; 
    } 

    public abstract Shape clone(); 

    public String toString() { 
     return str; 
    } 
} 

class Circle extends Shape { 

    public Circle(String str) { 
     super(str); 
    } 

    @Override 
    public Shape clone() { 
     return new Circle("circle"); 
    } 

} 
1

तरह परिभाषित करने के लिए बच्चे को कक्षा से पूछते हैं, आप प्रतिबिंब इस्तेमाल कर सकते हैं:

import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 

public class Test { 

    public static void main(String[] args) {   
     Square s1 = new Square("test"); 
     Square s2 = (Square) s1.clone(); 

     // show that s2 contains the same data 
     System.out.println(s2); 
     // show that s1 and s2 are really different objects 
     System.out.println(s1 == s2); 
    } 

    public static abstract class Shape { 
     private String str; 

     public Shape(String str) { 
      this.str = str; 
     } 

     public Shape clone() {   
      try { 
       Class<?> cl = this.getClass(); 
       Constructor<?> cons = cl.getConstructor(String.class); 
       return (Shape) cons.newInstance(this.toString());   
      } catch (NoSuchMethodException | SecurityException | 
        InstantiationException | IllegalAccessException | 
        IllegalArgumentException | InvocationTargetException e) { 
       e.printStackTrace(); 
      }   

      return null; 
     } 

     @Override 
     public String toString() { 
      return str; 
     } 
    } 

    public static class Square extends Shape { 
     public Square(String str) { 
      super(str); 
     } 
    } 
} 
1

आप प्रतिबिंब के साथ हल कर सकते हैं:

public abstract class Shape { 

    private String str; 

    public Shape() { 

    } 

    protected Shape(String str) { 
     this.str = str; 
    } 

    public Shape clone() throws CloneNotSupportedException 
    { 
     try { 
      return (Shape)getClass().getDeclaredConstructor(String.class).newInstance(this.toString()); 
     } catch (Exception e) { 
      throw new CloneNotSupportedException(); 
     } 
    } 

    public String toString() { 
     return "shape"; 
    } 

public class Round extends Shape 
{ 
    public Round() 
    { 
     super(); 
    } 
    protected Round(String str) { 
     super(str); 
    } 

    @Override 
    public String toString() { 
     return "round"; 
    } 
} 

main(){ 
    Shape round = new Round();   
    Shape clone = round.clone(); 
    System.out.println(round); 
    System.out.println(clone); 
} 

लेकिन - आईएमओ - बहुत कम गड्ढे के साथ एक खराब कार्यान्वयन और त्रुटि-प्रवण है; Cloneable और Object.clone() का सबसे अच्छा उपयोग उनका उपयोग नहीं करना है! आपके पास एक ही चीज करने के लिए बहुत कुछ तरीका है (जैसे गहरे क्लोन के लिए क्रमबद्धता) और उथले-क्लोन जो आपको प्रवाह के बेहतर नियंत्रण की अनुमति देते हैं।

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