2013-04-26 15 views
5

मैं किसी तृतीय पक्ष लाइब्रेरी में किसी फ़ैक्टरी द्वारा बनाई गई ऑब्जेक्ट को लपेटने के लिए प्रतिनिधिमंडल पैटर्न का उपयोग कर रहा हूं। हाल ही में, पुस्तकालय ने बेस क्लास में एक संरक्षित विधि जोड़ा और मेरा रैपर वर्ग अब काम नहीं करता है। क्या प्रतिबिंब का उपयोग किए बिना किसी के पास कोई अच्छा समाधान है?जावा: प्रतिनिधि पैटर्न और संरक्षित तरीके

यह 3 पार्टी पुस्तकालय में और उनके पैकेज में है,

public class Base { 
    public void foo(); 

    protected void bar(); // Newly added 
} 

यह मेरे अपने पैकेज में है,

public class MyWrapper extends Base { 
    private Base delegate; 

    public MyWrapper(Base delegate) { 
     this.delegate = delegate; 
    } 

    public void foo() { 
     delegate.foo() 
    } 

    protected void bar() { 
     // Don't know what to do 
    } 
} 

संपादित करें: मेरी मूल पोस्ट स्पष्ट नहीं था। ये 2 वर्ग अलग-अलग पैकेजों में हैं।

प्रश्न का उत्तर देने के लिए मुझे प्रतिनिधिमंडल की आवश्यकता क्यों है। यह प्रतिनिधिमंडल/रैपर पैटर्न का एक सामान्य उपयोग-मामला है और मैं इसे कोड की कुछ पंक्तियों में यहां नहीं दिखा सकता। लाइब्रेरी बेस क्लास का खुलासा करती है लेकिन उनके कारखाने से वास्तविक वस्तु बेस का व्युत्पन्न वर्ग है। कॉन्फ़िगरेशन के आधार पर वास्तविक वर्ग बदलता है। तो मुझे नहीं पता कि प्रतिनिधि क्या है। इसलिए सीधे विरासत पैटर्न यहां काम नहीं करता है।

+0

ठीक है, उस विधि का उद्देश्य क्या है? क्या आप इसे अनदेखा कर सकते हैं? मुझे नहीं लगता, जैसा कि आप कहते हैं "अब और काम नहीं करता है" ... क्या आप super.bar() को कॉल कर सकते हैं? नीले रंग में बस एक शॉट ... क्या आपके पास उस नई विधि पर कोई भी डॉकू है? – Fildor

+0

क्या आपने अपनी रैपर कक्षा को उसी वर्ग/पथ के साथ पैकेज में स्थानांतरित करने की कोशिश की है, जिसकी आधार कक्षा है ?? यह एक समाधान से अधिक हैक है लेकिन 'संरक्षित' विधियों को उसी पैकेज के भीतर सुलभ किया जाना चाहिए –

+1

बेस क्लास 'foo() 'और' bar() 'विधियों को लगता है जैसे' बेस' एक इंटरफेस या एक अमूर्त वर्ग था। क्या आप अपना प्रश्न निर्दिष्ट कर सकते हैं? आपको किस तरह से प्रतिबिंब की आवश्यकता होगी? चूंकि यह संरक्षित है, आपको इसे ओवरराइड करने की आवश्यकता नहीं हो सकती है। –

उत्तर

4
Access Levels 
Modifier Class Package Subclass World 
public  Y   Y  Y   Y 
protected Y   Y  Y   N 
no modifier Y   Y  N   N 
private  Y   N  N   N 

protected भी package पहुँच गया है, तो आप इस के साथ किसी भी विशिष्ट मुद्दा देख पा रहे हैं:

class Base { 
     public void foo(){}; 

     protected void bar(){}; // Newly added 
    } 

    class MyWrapper { 
     private Base delegate; 

     public MyWrapper(Base delegate) { 
      this.delegate = delegate; 
     } 

     public void foo() { 
      delegate.foo(); 
     } 

     protected void bar() { 
      // Don't know what to do 
      delegate.bar(); //since its in same package, it can be referenced, do you expect compile time error? 
     } 
    } 

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

+0

उचित –

+0

लगता है बेस क्लास एक तृतीय पक्ष लाइब्रेरी में है। मेरी कक्षा एक अलग पैकेज में है। –

+0

@ZZCoder आप अपनी लाइब्रेरी में एक ही पैकेज संरचना बना सकते हैं और फिर आपकी रैपर क्लास _same_ पैकेज में 'बेस' क्लास के रूप में होगी, यह एक प्रकार का हैक है और यह आपके रैपर के क्लाइंट कोड पर भ्रामक होगा , लेकिन कम से कम यह आपको उस संरक्षित विधि तक पहुंच प्रदान करेगा। मेरी पहली टिप्पणी में यही मेरा मतलब था। –

1

आपको उस बार विधि को प्रतिनिधि (या नहीं चाहिए?) की आवश्यकता नहीं है।

यदि पुस्तकालय एक संरक्षित विधि परिभाषित करता है। यह उस विधि का उपक्रम बनाने तक उपयोगकर्ता को (निश्चित रूप से विभिन्न पैकेज में) नहीं चाहता है, जब तक कि उस प्रकार के उप-वर्ग को न बनाये। आप नियम तोड़ने की कोशिश कर रहे हैं।

आप यह करने के लिए चाहते हैं, तो जिस तरह से आप Base की एक उप-प्रकार बनाने के लिए, SubBase कहना है, आप SubBase बजाय Base की वस्तु बनानी होगी, फिर आवरण को subBase गुजरती हैं। तो आप अपने आवरण में bar() विधि लिख सकता है delegate.bar() इस तरह, SubBase वास्तव में, प्रतिनिधि है या अपने आवरण SubBase नहीं Base

मुझे लगता है कि आप जानते हैं कि मैं क्या मतलब सौंपने है कहने के लिए है, तो मैं सिर्फ टाइप न करें उदाहरण कोड, केवल इस लाइन मुझे लगता है कि यह पर्याप्त है:

//Wrapper 

private SubBase delegate; 

तुम देखो अगर तुम SubBase है आवरण आवश्यक नहीं किसी भी अब है। आप अपने SubBase में public void pubBar() को भी परिभाषित कर सकते हैं, और वहां आप this.bar() पर कॉल करते हैं। इस तरह सबबेज की सभी वस्तुओं को संरक्षित विधि (via pubBar()) तक पहुंच है, इससे कोई फर्क नहीं पड़ता कि कौन सा पैकेज

+0

dovoter, pls कारण – Kent

1

मुझे लगता है कि Base कक्षा या तो एक इंटरफ़ेस या एक अमूर्त वर्ग है। यदि ऐसा है, तो आप bar() विधि लागू करें, उदाहरण के लिए नीचे सूचीबद्ध तीन विधियों में से किसी एक का उपयोग करके।

साइड ध्यान दें, यदि Base एक सामान्य वर्ग है, तो आप कुछ भी (MyWrapper.bar() का एक उदाहरण के लिए एक कॉल वास्तव में Base.bar() के लिए एक कॉल में परिणाम होगा करना नहीं है।


प्रतिनिधि पैरेंट ऑब्जेक्ट के लिए

यह आमतौर पर एक अच्छा विचार है अगर bar() विधि 3 पार्टी एपीआई में एक कॉलबैक के रूप में प्रयोग किया जाता है:

@Override 
protected void bar() { 
    delegate.bar(); 
} 

कुछ न करें

बस एक खाली विधि जोड़ा त्रुटियों संकलन से बचने के लिए:

@Override 
protected void bar() { 
    // silently ignored 
} 

हिंसक नई के किसी भी उपयोग को रोकने के लिए एक अपवाद

फेंक विधि:

@Override 
protected void bar() { 
    throw new UnsupportedOperationException("not implemented"); 
} 

एक तरफ ध्यान दें के रूप में, एक और अधिक मजबूत निर्माण 3 पार्टी कार्यान्वयन, उदा से अपने कार्यान्वयन दसगुणा composition over inheritance पसंद करते हैं करने के लिए है

public class MyWrapper { // does not extend Base 
    private Base delegate; 

    public MyWrapper(Base delegate) { 
     this.delegate = delegate; 
    } 

    public void foo() { 
     delegate.foo() 
    } 

    // does not have to implement bar() 
} 
+0

दे तो आप भी कह रहे हैं कि उसे 'बार' विधि को सही नहीं करना चाहिए, सही? आपके उदाहरण में उसके पास वैसे भी कोई विकल्प नहीं होगा। – Fildor

+0

@Fildor @ZZCoder मेरा अपडेट देखें। चूंकि 'बेस' से प्राप्त 'माईवॉपर' वर्ग को विरासत में प्राप्त किया गया है, इसलिए 'बेस 'एक सारणी वर्ग या इंटरफ़ेस है, तो' bar() 'विधि को लागू करना होगा। – matsev

+0

क्या इसे 'बेस' का विस्तार करना है? यदि नहीं, तो मैं matsev के wrapper के लिए जाना होगा जो विरासत से बचाता है। यदि हां, तो आपके सभी क्लाइंट नई विधि को नहीं जानते हैं, है ना? और मुझे लगता है कि आप इसे तीसरे पक्ष के lib में संदर्भ नहीं दे रहे हैं ... इसलिए उस मामले में मैं बस एक खाली "डमी" लागू करूँगा। – Fildor

0

मैं आवरण में एक और मॉड्यूल से "बेस प्रतिनिधि" इंजेक्शन लगाने के लिए और प्रतिनिधि हो रही मैं एक POJO कारखाना उपयोग कर रहा हूँ के लिए वसंत का उपयोग कर रहा हूँ।

<bean id="interfaceDelegate" factory-bean="DelegatePojoFactory" 
    factory-method="getMyDelegateInstance"> 
    <constructor-arg index="0"> 
     <value>OnLine</value> 
    </constructor-arg> 
</bean> 

<bean id="wrapper" class="path.Wrapper"> 
     <property name="delegate" ref="interfaceDelegate"></property> 
</bean> 
0

आप अपने डैलिगेटर की जरूरत नहीं है आधार वर्ग का एक वास्तविक उदाहरण हो सकता है, तो आप बस उस संबंध को दूर कर सकते हैं:

public class MyWrapper { 
    private Base delegate; 

    public MyWrapper(Base delegate) { 
     this.delegate = delegate; 
    } 

    public void foo() { 
     delegate.foo() 
    } 

} 

चाहे जो आपके बहुत काम अपने अन्य पर बहुत निर्भर है कोड, और आपकी ज़रूरतें अभी मुझे पूरी तरह स्पष्ट नहीं हैं।

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

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