2015-03-10 14 views
8

हाल ही में मेरे पास एक साक्षात्कार था और मुझे निम्नलिखित प्रश्न पूछा गया। यह देखते हुए निम्नलिखित वर्ग/इंटरफेस संरचना:एक बाल इंटरफ़ेस अपने माता-पिता के कार्यान्वयन का पुन: उपयोग कैसे कर सकता है?

enter image description here

प्रश्न:

एक इंटरफेस EmployedStudent को लागू कैसे StudentImpl और EmployeeImpl से कोड का पुन: उपयोग कर सकते हैं।

मैंने अपने कार्यान्वयन में कर्मचारी और छात्र लिखने का सुझाव दिया।

साक्षात्कारकर्ता की प्रतिक्रिया के आधार पर मुझे नहीं लगता कि उन्हें यह सबसे अच्छा समाधान माना जाता है। मैंने इसके बारे में सोचने में बहुत समय बिताया लेकिन मैं एक और समाधान के साथ नहीं आ सकता।

+0

कोड पुन: उपयोग के संदर्भ में संरचना मेरे लिए सबसे अच्छा तरीका है। एकाधिक विरासत के बिना, मुझे नहीं पता कि आप * * * StudentImpl' और 'EmployeeImpl' दोनों से कोड का पुन: उपयोग कैसे करेंगे। – christopher

+1

मैंने रचना भी कहा होगा। आप * कार्यान्वयन में से एक से 'नियोजित स्टूडेंट' प्राप्त कर सकते हैं और फिर मुझे लगता है कि दूसरे के लिए संरचना का उपयोग करने की आवश्यकता है। लेकिन मैंने यह नहीं कहा होगा कि सीधे संरचना की तुलना में वास्तव में बेहतर था जब तक कि इंटरफेस में से एक दूसरे की तुलना में अधिक "प्राथमिक" नहीं है (उदाहरण के लिए, प्राथमिक पहलू यह था कि यह एक कर्मचारी था, जिसमें छात्र थोड़ा माध्यमिक था)। इंटरफेस का उपयोग करते हुए –

उत्तर

1

जावा एकाधिक वंशानुक्रम का समर्थन नहीं करता है, आप कर सकते थे/

  • या तो वांछित सुपर-क्लास से प्रत्येक के लिए एक क्षेत्र होना चाहिए
  • या एक सुपर क्लास से निकाले जाते हैं और एक दूसरे के लिए कोई फ़ील्ड।

फ़ील्ड्स को संबंधित तरीकों के "हमारे" कार्यान्वयन द्वारा संदर्भित किया जाता है।

यह design patterns from the GoF में से एक है, मुझे लगता है कि यह Proxy pattern है।

5

एक ऐसी कक्षा बनाएं जो Employee और Student दोनों लागू करती है। अपनी कक्षा में, EmployeeImpl और StudentImpl दोनों का एक उदाहरण बनाएं। तब अपनी कक्षा को ऑब्जेक्ट्स में से किसी एक को सभी विधि कॉल प्रतिनिधि बनाएं।

public class EmployedStudent implements Employee, Student { 

    private EmployeeImpl employee = new EmployeeImpl(); 
    private StudentImpl student = new StudentImpl(); 

    public int getSalary() { 
    return this.employee.getSalary(); 
    } 

    public float getAverageGrade() { 
    return this.student.getAverageGrade(); 
    } 

} 
+1

, मैं वास्तव में इंटरफेस न केवल कर्मचारी और छात्र वर्गों में मौजूदा कोड का उपयोग करने की तरह प्रश्न को समझता हूं। –

+2

@meister_reineke: प्रतिनिधिमंडल के माध्यम से, आप वास्तव में * 'कर्मचारी Impl'' और' StudentImpl'' वर्ग के मौजूदा कोड का उपयोग करेंगे। – user1438038

1

जावा 8 के साथ, आप कोड को इंटरफ़ेस में ही स्थानांतरित कर सकते हैं। यह "एकाधिक विरासत" समस्या हल करता है।

1

इंटरफ़ेस पृथक्करण सिद्धांत कभी कभी सहायक हो सकता है, और कुछ लोगों इंटरफेस जो वादा नहीं करते है कि सभी क्रियान्वयन सभी सदस्यों का समर्थन करेंगे के विचार पर हँसी है, मेरा सुझाव है कि यह Student और Employee इंटरफेस के लिए सहायक हो सकता है कि जिसमें isStudent और isEmployee सदस्य शामिल हैं, और उसके बाद Person दोनों इंटरफेस लागू करते हैं; giveRaise() जैसे कुछ तरीकों को किसी ऐसे कर्मचारी पर काम नहीं करना चाहिए जो कर्मचारी नहीं है, लेकिन getOutstandingPay() जैसे अन्य लोगों को ठीक काम करना चाहिए (अगर किसी ने कोई पैसा नहीं कमाया है, तो विधि को शून्य वापस करना चाहिए)।

हालांकि यह Person ऑब्जेक्ट्स को उन तरीकों से जटिल करने के लिए बदसूरत प्रतीत हो सकता है जो उनमें से कई के लिए लागू नहीं होंगे, ऐसे डिज़ाइन में छात्र को किराए पर लेने की स्थिति में कठिनाइयों से बचा जाता है, या कोई कर्मचारी कक्षाएं लेना शुरू कर देता है। Student, Employee, और StudentEmployee लिए अलग-अलग वर्गों के बाद, भले ही एक इतनी आसानी से कर सकता है, की आवश्यकता होगी कि एक Student जो एक नौकरी मिल गई है, ताकि एक StudentEmployee बनने के लिए एक नई वस्तु उदाहरण के साथ प्रतिस्थापित किया। इसके विपरीत, यदि किसी के पास Person वर्ग है जिसका उदाहरण giveRaise जैसी विधियों को संभालने में सक्षम नहीं हो सकता है, तो कोई ऐसी स्थितियों को संभाल सकता है जहां वस्तुओं की क्षमताओं को उनके जीवनकाल में बदल दिया जाता है।

3

तो, आप implements Employee, Student आंतरिक रूप से कर्मचारी Iplpl और StudentImpl दोनों को प्रतिनिधि दे सकते हैं, लेकिन एक कार्यान्वयन कक्षा से भी उत्तराधिकारी हो सकते हैं।

अब वर्ग नाम EmployedStudent (StudyingEmployee या BothEmployeeAndStudent नहीं) पता चलता है:

class EmployedStudent extends StudentImpl implements Employee { 
    Employee asEmployee = new EmployeeImpl(); 

हाँ, एक छोटा सा केवल एक अन्य वर्ग के लिए सौंपने के रूप में और अधिक कुशल।

उपयोग-मामला यथार्थवादी से बहुत दूर है: सभी तरह के संयोजन कई वर्गों के बारे में सोचते हैं। उस स्थिति में आपका समाधान अधिक सार्वभौमिक है।

public class Person { 
    public <T> T as(Class<T> klazz) { ... } 
} 

Person person = ...; 
Student asStudent = person.as(Student.class); 
if (asStudent != null) { 
    ... 
} 
Employee asEmployee = person.as(Employee.class); 
if (asEmployee != null) { 
    asEmployee.quitJob(); 
    asEmployee = person.as(Employee.class); // null 
} 

क्षमताओं के देखने है: सच में सार्वभौमिक, एक देखने-तंत्र है। स्विमिंग, फ्लाइंग, ड्राइविंग क्षमताओं का उपयोग करके वाहन, रोडविहिकल, स्विमिंग वेहिकल (नाव), फ्लाइंगवहिकल (एयर प्लेन), वाटरएयरप्लेन (?), एम्फिबियनटैंक (?) के बारे में कहते हैं, यह आमतौर पर एक बोझिल विरासत पदानुक्रम को प्रतिस्थापित कर सकता है।

अंतर पूरे decoupling है।

+0

यह एक शानदार ठंडा कामकाज है! मुझे यकीन नहीं है कि मैं इस तरह की रचना पर कुछ ऐसा करने के लिए जाऊंगा, लेकिन यह निश्चित रूप से दिखाता है कि आप * इस कार्यक्षमता को अनुकरण कर सकते हैं। – christopher

+0

मैंने विधि के बारे में आपके विचार को नहीं पकड़ा। व्यक्ति वर्ग क्या है? – gstackoverflow

+0

यह दिखाने का इरादा है कि एक उत्तर दो अन्य लाइनों को एक और दृष्टिकोण दिखाकर प्रदान कर सकता है। लेकिन निश्चित रूप से _that_ का उल्लेख करें: "इसी तरह के उपयोग में-मामलों में भी कोई भी ...", उत्तर विस्तारित किया गया। –

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

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