2013-06-12 3 views
8

इंटरफ़ेस सदस्य चर के साथ कक्षा के लिए आप एक प्रतिलिपि कैसे लिखेंगे?क्या जावा में इंटरफ़ेस सदस्य चर के साथ कक्षाओं के लिए कॉपी कन्स्ट्रक्टर लिखना संभव है?

उदाहरण के लिए:

public class House{ 

    // IAnimal is an interface 
    IAnimal pet; 

    public House(IAnimal pet){ 
     this.pet = pet; 
    } 

    // my (non-working) attempt at a copy constructor 
    public House(House houseIn){ 
     // The following line doesn't work because IAnimal (an interface) doesn't 
     // have a copy constructor 
     this.pet = new IAnimal(houseIn.pet); 
    } 
} 

Am मैं एक ठोस Animal है करने के लिए मजबूर? यदि ऐसा है, तो ऐसा लगता है कि बिल्लियों के साथ कुत्तों बनाम घरों वाले घरों के लिए कक्षा का पुन: उपयोग करना प्रतीत होता है!

+1

यदि आप एक गहरी प्रतिलिपि चाहते हैं तो आपको पशु में एक प्रति-निर्माता भी लागू करना चाहिए। – alfasin

+1

आप पशु में एक कॉपी-कन्स्ट्रक्टर को बस कार्यान्वित नहीं कर सकते हैं। इस मामले में आपके पास एक इंटरफ़ेस IAimal है। इसलिए आपको यह जानने की आवश्यकता होगी कि आपको किस ठोस वर्ग को तत्काल करने की आवश्यकता है। – Mene

उत्तर

6

आप तीन में से एक विकल्प हैं:

  1. IAnimal पर एक विधि गहरा वस्तु क्लोन करने के लिए है (द्वारा प्रयोग किया जाता Node.cloneNode(boolean) जैसे डीओएम इंटरफेस जैसे पुस्तकालय)
  2. IAnimal के सभी कार्यान्वयन में एक कॉपी कन्स्ट्रक्टर बनाएं जो ठोस प्रकार लेता है और उसे एक आवश्यकता बना देता है इंटरफ़ेस अनुबंध में एनटी, फिर इसे
  3. प्रत्येक प्रति कार्यान्वयन की प्रतिलिपि बनाने के लिए प्रतिबिंब का उपयोग करें
  4. एक तृतीय-पक्ष लाइब्रेरी का उपयोग करें जो आपके अनुबंधों के साथ गहरे क्लोनिंग को लागू करता है, जैसे नो-Args रचनाकार, गैर-अंतिम फ़ील्ड, Serializable कक्षाएं, इत्यादि।, सूचीबद्ध here

कॉपी विधि

# 1 के लिए प्रश्न, जैसे कर कुछ की तरह:

public interface IAnimal { 
    IAnimal cloneDeep(); 
} 

लागू है कि आपके ठोस प्रकार में, तो उस विधि आह्वान इसे कॉपी:

this.pet = pet.cloneDeep(); 

फिर इंटरफ़ेस में आवश्यकता को दस्तावेज़ करें, कह रहा है की तर्ज पर omething:

इस इंटरफेस एक वस्तु है कि इस उदाहरण के लिए नहीं == है, और गहराई से क्लोन किया जाना चाहिए ताकि इस वस्तु की कि हेरफेर लौटे एक के हेरफेर करने के लिए नेतृत्व नहीं करता है लौटना चाहिए की क्रियान्वयन और इसके विपरीत।

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

कॉपी निर्माता

प्रयास करें, तो राज्य है कि एक प्रति निर्माता इंटरफ़ेस है, जो इंटरफेस अनुबंध का हिस्सा बन जाता में सभी ठोस कार्यान्वयन में आवश्यक है। प्रत्येक कार्यान्वयन तो इस प्रकार दिखाई देगा:

public class Dog implements IAnimal { 

    private String name; 

    public Dog(Dog dog) { 
     this.name = dog.name; 
    } 
} 

और फिर आप सभी की जरूरत हर कार्यान्वयन प्रतिलिपि बनाने में एकल विधि है:

public static <A extends IAnimal> A copy(A animal) { 
    Class<?> animalType = animal.getClass(); 
    // This next line throws a number of checked exceptions you need to catch 
    return (A) animalType.getConstructor(animalType).newInstance(animal); 
} 

एक तो आप इस किया है, अपने इंटरफेस के दशक में इस आशय का एक बयान जोड़ने प्रलेखन:

इस इंटरफेस की

क्रियान्वयन एक प्रति निर्माता है कि एक ही प्रकार या उनके वर्ग के महाप्रकार का एक तर्क लेता है परिभाषित करना होगा। इस कन्स्ट्रक्टर को तर्क की एक गहरी प्रतिलिपि बनाना चाहिए ताकि इस वस्तु के हेरफेर से लौटाए गए व्यक्ति के हेरफेर और इसके विपरीत नहीं हो सके।

फिर, यह रनटाइम लागू है। copy उपरोक्त विधि NoSuchMethodException त्रुटियों को फेंकता है जब निर्माता मौजूद नहीं है।

कॉपी फैक्टरी

यह IAnimal लेता है और instanceof का उपयोग करता है तय करने के लिए कौन सी विधि, करने के लिए इसे पारित करने के लिए की तरह:

public static IAnimal copyAnimal(IAnimal animal) { 
    if (animal instanceof Dog) 
     return copyDog((Dog) animal); 
    if (animal instanceof Cat) 
     return copyCat((Cat) animal); 
    //... 
    else 
     throw new IllegalArgumentException("Could not copy animal of type: " 
       + animal.getClass().getName()); 
} 

तो प्रत्येक प्रकार के लिए copy तरीकों में गहरी नकल कर मैन्युअल रूप से ।

0

मेरे ज्ञान के लिए जावा में इसका कोई प्रत्यक्ष समतुल्य नहीं है।

"उचित" तरीका इंटरफेस को Cloanable लागू करने के लिए है।

और प्रतिबिंब का उपयोग करने का सबसे आसान तरीका हो सकता है। मुझे पता है कि एक पुस्तकालय है जो मनमानी वस्तुओं की गहरी प्रतियों को संभालती है, लेकिन मुझे इस समय नाम याद नहीं है।

संबंधित: Java: recommended solution for deep cloning/copying an instance

+2

'क्लोनेबल' तरीकों के समूह में टूट गया है, और 'प्रभावी जावा' में जोश ब्लोच इसका उपयोग नहीं करने की सिफारिश करता है। यदि आपके पास वह पुस्तक नहीं है, तो आपको चाहिए। देखें: http://www.artima.com/intv/bloch13.html –

2

अगर मैं आपकी समस्या को समझते हैं, जब से तुम एक अंतरफलक में कंस्ट्रक्टर्स निर्दिष्ट नहीं कर सकते हैं कि आप अपने इंटरफ़ेस में एक गहरे प्रतिलिपि प्रणाली की घोषणा और अपनी कक्षाओं में इसे लागू करने की आवश्यकता होगी। आप एक इंटरफ़ेस को तुरंत चालू नहीं कर सकते हैं। आप संभवतः House में अपनी आवश्यकताओं के आधार पर कुछ भी गहरी प्रतिलिपि बनाना चाहते हैं।

public interface IAnimal { 
    ... 
    IAnimal deepCopy(); 
} 


public House(House houseIn){ 
    this.pet = houseIn.pet.deepCopy(); 
} 

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

1

ठीक है, मुझे इस कोड में एक समस्या बताएं। ध्यान दें कि जब आपके पास एक इंटरफ़ेस होता है तो आप किसी व्यवहार को परिभाषित नहीं कर रहे हैं, किसी ऑब्जेक्ट (या जीव) जैसे किसी पशु की अमूर्तता या पहचान नहीं। इस मामले पर आपको एक इंटरफेस के बजाय एक अमूर्त वर्ग की आवश्यकता है। जो शुरू हुआ। आपके पास इंटरफ़ेस पर कोई कन्स्ट्रक्टर नहीं हो सकता है (इसलिए Why are we not allowed to specify a constructor in an interface? देखें) इसलिए इंटरफ़ेस का उपयोग करके इस तरह असफल हो जाएगा।

इसलिए इस मामले पर मैं बजाय एक अमूर्त वर्ग का उपयोग कर सुझाव है:

public class House { 

AbstractAnimal pet; 

public House(AbstractAnimal pet) { 
    this.pet = pet; 
} 

public House(House houseIn) { 
    this.pet = new AbstractAnimal(houseIn.pet) { 
     //implement the abstract methods that are required for anonymous class 
    }; 
} 

private abstract class AbstractAnimal { 
    //Abstract class attributes 

    public AbstractAnimal(AbstractAnimal Parent) { 
     //Constructor code, can also call abstract methods if required 
    } 
    //declare Abstract methods if required. 
} 
संबंधित मुद्दे