मुझे विरासत और स्कैला में निचली सीमाओं के साथ कुछ समस्याएं आ रही हैं; मैं इसे एक उदाहरण के साथ समझाने की कोशिश करूंगा: मेरे पास एक वर्ग व्यक्ति है जिसके हस्ताक्षर हैं:

def doSomething[P<%Person](persons :List[P]) {
}

मैंने एक चाइल्ड क्लास वर्कर भी बनाया है, और उसकी विधि कुछ इस तरह दिखती है:

override def doSomething(persons: List[Worker]) {
}

हालांकि यह एक त्रुटि को सक्रिय करता है, जिसमें कहा गया है कि Worker.doSomething() कुछ भी ओवरराइड नहीं करता है?

2
user485659 6 नवम्बर 2011, 01:13

2 जवाब

सबसे बढ़िया उत्तर

आप इस तरह से विरासत में नहीं मिल सकते। यह लिस्कोव प्रतिस्थापन सिद्धांत का उल्लंघन करता है। मैं दिखाऊंगा कि ऐसा क्यों है। मान लीजिए कि आप इन वर्गों को संकलित कर सकते हैं:

class Person {
    def doSomething[P<%Person](persons :List[P]) {
    }
}

class Worker extends Person {
    override def doSomething(persons: List[Worker]) {
    }
}

अब, यह सरल कार्यक्रम विफल हो जाएगा:

val p1: Person = new Worker
val p2: Person = new Person
p1.doSomething(List(p2))

चूंकि p2 Worker नहीं है, इसलिए वह कॉल अमान्य है। हालांकि, चूंकि p1 एक Person है, वह कॉल मान्य है! यह विरोधाभास आपके द्वारा प्रस्तावित ओवरराइड का परिणाम है।

लेकिन यह उससे भी बुरा है! यह भी काम नहीं करेगा:

p1.doSomething[Worker](List(p1))

अब, भले ही यह p1 द्वारा अपेक्षित श्रमिकों की एक सूची पारित कर रहा है, यह विफल हो जाता है क्योंकि doSomething में Worker एक प्रकार के पैरामीटर की अपेक्षा नहीं करता। हालांकि, Person की विधि doSomething ने घोषणा की कि एक प्रकार का पैरामीटर पारित किया जाना चाहिए! फिर, विरोधाभास आपके द्वारा प्रस्तावित ओवरराइड का परिणाम है।

याद रखें कि विरासत एक एक है तरह का संबंध है। यदि Worker एक Person है, तो उसे एक Person की तरह कार्य करना चाहिए, जिस तरह से एक Person से कार्य करने की अपेक्षा की जाती है। यदि आप उस प्रकार का संबंध नहीं बनाना चाहते हैं, तो विरासत का उपयोग न करें।

3
Daniel C. Sobral 6 नवम्बर 2011, 04:13

एक विशिष्ट विधि एक सामान्य विधि को ओवरराइड नहीं कर सकती है (हालांकि एक विशिष्ट वर्ग एक सामान्य वर्ग का विस्तार कर सकता है) क्योंकि सामान्य विधि कहती है कि यह तब तक काम करेगी जब तक आप इसे किसी भी व्यक्ति के उपवर्ग को पास करते हैं। विशिष्ट विधि कोई उपवर्ग नहीं लेगी; यह केवल Worker लेगा।

4
Rex Kerr 6 नवम्बर 2011, 01:43
आपके उत्तर के लिए धन्यवाद, हालांकि Worker.doSomething() विधि में मैं वर्कर वर्ग (जो सामान्य व्यक्ति वर्ग में नहीं हैं) की विशेषताओं तक पहुंच बनाना चाहता हूं। क्या इन गुणों (कास्टिंग के बिना) तक पहुंचने का कोई तरीका है?
 – 
user485659
6 नवम्बर 2011, 02:28
- आप जो करने की कोशिश कर रहे हैं, क्या आप उसका थोड़ा और वर्णन कर सकते हैं? जैसा कि मेरा उत्तर हाइलाइट करता है, कक्षा को ओवरराइड करना तार्किक रूप से गलत है; कास्टिंग भी (तार्किक रूप से, यदि व्यावहारिक रूप से नहीं) गलत होगा, क्योंकि कास्ट विफल हो सकता है (यानी उस विधि को केवल सूची [कार्यकर्ता] के साथ सामान्य कोड में तर्क के रूप में कॉल करने की कोई गारंटी नहीं है जो व्यक्तियों के साथ काम करता है)।
 – 
Rex Kerr
6 नवम्बर 2011, 02:38
यदि आपका कोई अन्य प्रश्न है, तो उसे दूसरे प्रश्न में पूछें। लेकिन, संक्षेप में, आपको कभी भी किसी वस्तु के बारे में कुछ नहीं पूछना चाहिए; इसके बजाय आपको यह बताना चाहिए कि क्या करना है, इस मामले में यह यांत्रिकी का ही ख्याल रखता है। हालांकि, अच्छी प्रथाओं से बचने के लिए आप पैटर्न मिलान का उपयोग कर सकते हैं।
 – 
Daniel C. Sobral
6 नवम्बर 2011, 04:15