क्या रिश्ते को उलट कर सर्कल-एलिप्से समस्या हल की जा सकती है?


13

Circleविस्तारितEllipse होने से लिस्कोव पदार्थ सिद्धांत टूट जाता है , क्योंकि यह एक पोस्टकंडिशन को संशोधित करता है: अर्थात्, आप एक्स और वाई को स्वतंत्र रूप से एक दीर्घवृत्त खींचने के लिए सेट कर सकते हैं, लेकिन एक्स को हमेशा हलकों के लिए वाई के बराबर होना चाहिए।

लेकिन क्या यहाँ समस्या यह नहीं है कि सर्किल एक दीर्घवृत्त का उपप्रकार हो सकता है? क्या हम रिश्ते को उलट नहीं सकते थे?

तो, सर्किल सुपरपाइप है - इसकी एक एकल विधि है setRadius

फिर, एलिप्से सर्कल को जोड़कर setXऔर बढ़ाता है setYsetRadiusएलिप्से पर कॉल करने से एक्स और वाई दोनों सेट होंगे - मतलब सेटराडियस पर पोस्टकॉन्डिशन बनाए रखा जाता है, लेकिन अब आप एक्स और वाई को एक विस्तारित इंटरफ़ेस के माध्यम से स्वतंत्र रूप से सेट कर सकते हैं।


1
क्या आपने पहले विकिपीडिया ( en.wikipedia.org/wiki/Circle-ellipse_problem ) को देखा?
डॉक्टर ब्राउन

1
हां - मैं इसे अपने प्रश्न में भी
जोड़ता

6
और यह सटीक बिंदु उस लेख में शामिल है, इसलिए मैं स्पष्ट नहीं हूं कि आप क्या पूछ रहे हैं?
फिलिप केंडल

6
"कुछ लेखकों ने सर्कल और दीर्घवृत्त के बीच के संबंधों को उलटने का सुझाव दिया है, इस आधार पर कि एक दीर्घवृत्त अतिरिक्त क्षमताओं वाला एक चक्र है। दुर्भाग्य से, सर्कल के कई आक्रमणकारियों को संतुष्ट करने में दीर्घवृत्त विफल होते हैं; यदि सर्कल में एक विधि त्रिज्या है, तो एलिप्से अब होगा। साथ ही इसे प्रदान करने के लिए। ”
फिलिप केंडल

3
मुझे इस बात के बारे में सबसे स्पष्ट स्पष्टीकरण मिला कि इस समस्या के कारण विकिपीडिया लेख के बहुत निचले भाग में खराब स्थिति क्यों है: en.wikipedia.org/wiki/… । स्थिति की निर्भर करता है, वहाँ कई स्वच्छ डिजाइन है, लेकिन यह इन दो वर्गों से आप की जरूरत क्या की निर्भर करता है ऐसा , नहीं करने के लिए हो सकता है
आर्थर हेवलिसक

जवाबों:


38

लेकिन क्या यहाँ समस्या यह नहीं है कि सर्किल एक दीर्घवृत्त का उपप्रकार हो सकता है? क्या हम रिश्ते को उलट नहीं सकते थे?

इस समस्या के साथ (और वर्ग / आयत समस्या) एक डोमेन (ज्यामिति) में एक रिश्ते को दूसरे तरीके से मानना ​​गलत है (व्यवहार)

यदि आप उन्हें ज्यामितीय सिद्धांत के चश्मे के माध्यम से देख रहे हैं तो एक वृत्त और दीर्घवृत्त संबंधित हैं। लेकिन यह एकमात्र ऐसा डोमेन नहीं है जिसे आप देख सकते हैं।

व्यवहार के साथ वस्तु उन्मुख डिजाइन सौदों ।

किसी वस्तु की परिभाषित विशेषता वह व्यवहार है जिसके लिए वस्तु जिम्मेदार होती है। और व्यवहार के क्षेत्र में, एक सर्कल और दीर्घवृत्त में ऐसा अलग व्यवहार होता है कि यह संभव नहीं है कि उन्हें बिल्कुल भी संबंधित न समझें। इस डोमेन में, एक दीर्घवृत्त और एक वृत्त का कोई महत्वपूर्ण संबंध नहीं है।

यहाँ सबक उस डोमेन को चुनना है जो OOD के लिए सबसे अधिक समझ में आता है, न कि कोशिश करना और एक रिश्ते में केवल इसलिए जूते करना क्योंकि यह एक अलग डोमेन में मौजूद है।

इस गलती का सबसे आम वास्तविक दुनिया उदाहरण यह है कि ऑब्जेक्ट संबंधित (या यहां तक ​​कि एक ही वर्ग) हैं क्योंकि उनके पास समान डेटा है भले ही उनका व्यवहार बहुत अलग हो। यह एक आम समस्या है जब आप वस्तुओं को "डेटा पहले" बनाना शुरू करते हैं, जहां डेटा जाता है। आप एक वर्ग के साथ समाप्त हो सकते हैं जो डेटा के माध्यम से संबंधित होते हैं जो पूरी तरह से अलग व्यवहार करते हैं। उदाहरण के लिए, दोनों भुगतान और कर्मचारी वस्तुओं में "सकल वेतन" विशेषता हो सकती है, लेकिन एक कर्मचारी एक प्रकार का भुगतान नहीं है और एक भुगतान-पत्र कर्मचारी का एक प्रकार नहीं है।


(आवेदन) डोमेन बनाम OOD के व्यवहार और जिम्मेदारी क्षमताओं की चिंताओं को अलग करना एक बहुत ही महत्वपूर्ण बिंदु है। उदाहरण के लिए, एक ड्राइंग एप्लिकेशन में, आपको शायद एक वर्ग में एक सर्कल को आकार देने में सक्षम होना चाहिए, लेकिन यह आसानी से अधिकांश भाषाओं में कक्षाओं / ऑब्जेक्ट्स का उपयोग करके मॉडलिंग नहीं की जाती है (क्योंकि ऑब्जेक्ट आमतौर पर क्लास को बदल नहीं सकते हैं)। इसलिए, एप्लिकेशन डोमेन हमेशा किसी दिए गए OOP भाषा की विरासत पदानुक्रम को अच्छी तरह से मैप नहीं करता है और हमें इसके लिए मजबूर करने की कोशिश नहीं करनी चाहिए; कई मामलों में, रचना बेहतर है।
एरिक Eidt

3
यह उत्तर अभी तक पूरे मामले के बारे में सबसे अच्छी बात है, और अधिक सामान्य मामलों में डिजाइन की गलतियों की संभावना कैसे पैदा हो सकती है। धन्यवाद
HorusKol

1
@ErikEidt एक वस्तु बदलने वाले व्यवहार की समस्या को अपघटन के माध्यम से OOD में हल किया जा सकता है। उदाहरण के लिए यदि एक आकृति का आकार चक्र में बदल जाता है, तो आपको कक्षा में परिवर्तन करने की आवश्यकता नहीं है। इसके बजाय वर्ग एक वर्तमान ज्यामितीय व्यवहार वस्तु लेता है जिसे आप मॉर्फ करने पर दूसरे व्यवहार के लिए स्वैप कर सकते हैं। इस अन्य वर्ग में वर्तमान में मॉडल किए जा रहे ज्यामितीय आकार के नियम शामिल हैं, और ज्यामितीय व्यवहार के लिए इस वर्ग के लिए आकृति आकृति वर्ग दोष है। यदि ऑब्जेक्ट एक अलग वर्ग में रूपांतरित होता है तो आप व्यवहार वर्ग को किसी और चीज़ में बदलते हैं।
कॉर्मैक मुल्हल

2
@Cormac, सही है! आम तौर पर मैं रचना का एक रूप कहूंगा, जैसा कि मैंने उल्लेख किया है, हालांकि आप पहचान सकते हैं, अधिक विशेष रूप से, एक रणनीति पैटर्न या कुछ और। संक्षेप में, आपके पास एक ऐसी पहचान है जो मॉर्फ नहीं करती है, और अन्य चीजें जिन्हें तब बदला जा सकता है। अनुप्रयोग डोमेन अवधारणाओं और किसी दिए गए भाषा के OOP के विवरणों और उनके (यानी आर्किटेक्चर, डिज़ाइन और प्रोग्रामिंग) के बीच मैप करने की आवश्यकता के बीच अंतर पर एक अच्छी हाइलाइटिंग में सभी।
एरिक इद्दत

1
लेकिन एक नौकरी एक पेचेक हो सकती है।

8

मंडलियां दीर्घवृत्त का एक विशेष मामला है, अर्थात् दीर्घवृत्त के दोनों अक्ष एक समान हैं। यह समस्या डोमेन (ज्यामिति) में मौलिक रूप से गलत है कि ईलिप्स एक तरह का चक्र हो सकता है। इस त्रुटिपूर्ण मॉडल का उपयोग करने से सर्कल की कई गारंटी का उल्लंघन होगा, उदाहरण के लिए "सर्कल के सभी बिंदुओं की केंद्र की दूरी समान है"। वह भी लिस्कोव सबस्टीट्यूशन सिद्धांत का उल्लंघन होगा। कैसे एक दीर्घवृत्त एक एकल त्रिज्या होगा? (नहीं setRadius()बल्कि अधिक महत्वपूर्ण बात getRadius())

जबकि दीर्घवृत्त के उपप्रकार के रूप में मंडलियों का मॉडलिंग मौलिक रूप से गलत नहीं है, यह परिवर्तनशीलता का परिचय है जो इस मॉडल को तोड़ता है। तरीकों setX()और setY()तरीकों के बिना , कोई एलएसपी उल्लंघन नहीं है। यदि विभिन्न आयामों के साथ कोई वस्तु होनी चाहिए, तो एक नया उदाहरण बनाना एक बेहतर उपाय है:

class Ellipse {
  final double x;
  final double y;
  ...
  Ellipse withX(double newX) {
    return new Ellipse(x: newX, y: y);
  }
}

1
ठीक है - इसलिए, अगर Ellipseऔर Circle(जैसे getArea) के बीच कुछ सामान्य इंटरफ़ेस थे जो एक प्रकार के लिए सारगर्भित होंगे Shape- एलएसपी को संतुष्ट Ellipseऔर Circleअलग-अलग उप-प्रकार से कर सकते हैं Shape?
होरसकॉल

1
@ हॉर्सकॉल हां। दो वर्गों को एक इंटरफ़ेस विरासत में मिला है, जिसे वे वास्तव में सही ढंग से लागू करते हैं, पूरी तरह से ठीक है।
Ixrec

7

कॉर्मैक का वास्तव में बहुत अच्छा जवाब है, लेकिन मैं सिर्फ पहले स्थान पर भ्रम के कारण पर थोड़ा विस्तार करना चाहता हूं।

OO में विरासत को अक्सर वास्तविक दुनिया के रूपकों का उपयोग करके सिखाया जाता है, जैसे "सेब और संतरे दोनों फल के उप-वर्ग हैं"। दुर्भाग्य से यह गलत धारणा है कि OO के प्रकारों को प्रोग्राम के मौजूदा स्वतंत्र कुछ करणीय पदानुक्रमों के अनुसार मॉडलिंग की जानी चाहिए।

लेकिन सॉफ्टवेयर डिजाइन में, एप्लिकेशन की आवश्यकताओं के अनुसार प्रकारों को मॉडल किया जाना चाहिए। अन्य डोमेन में वर्गीकरण आमतौर पर अप्रासंगिक हैं। "ऐप्पल" और "ऑरेंज" वस्तुओं के साथ एक वास्तविक अनुप्रयोग में - एक सुपरमार्केट के लिए एक इन्वेंट्री प्रबंधन प्रणाली कहते हैं - वे शायद अलग-अलग वर्ग नहीं होंगे, और "फ्रूट" जैसी श्रेणियां सुपरटेप्स के बजाय गुण होंगे।

सर्कल-एलिप्से समस्या एक लाल हेरिंग है। ज्यामिति में एक वृत्त एक दीर्घवृत्त का एक विशेषज्ञता है, लेकिन आपके उदाहरण में कक्षाएं ज्यामितीय आंकड़े नहीं हैं। महत्वपूर्ण रूप से, ज्यामितीय आंकड़े परस्पर नहीं हैं। उन्हें रूपांतरित किया जा सकता है , हालांकि, लेकिन फिर एक वृत्त को एक दीर्घवृत्त में परिवर्तित किया जा सकता है। तो एक मॉडल जहां मंडलियां त्रिज्या को बदल सकती हैं लेकिन एक दीर्घवृत्त में नहीं बदलती हैं, ज्यामिति के अनुरूप नहीं है। इस तरह के एक मॉडल एक विशेष अनुप्रयोग (एक ड्राइंग टूल कह सकते हैं) में समझ में आता है, लेकिन ज्यामितीय वर्गीकरण इस बात के लिए अप्रासंगिक है कि आप वर्ग पदानुक्रम कैसे डिज़ाइन करते हैं।

तो क्या सर्किल को एलिप्से का उपवर्ग या इसके विपरीत होना चाहिए? यह पूरी तरह से उस विशेष एप्लिकेशन की आवश्यकताओं पर निर्भर करता है जो इन वस्तुओं का उपयोग करता है। एक ड्राइंग एप्लिकेशन में हलकों और दीर्घवृत्त के उपचार के विभिन्न विकल्प हो सकते हैं:

  1. अलग-अलग UI के साथ अलग-अलग प्रकार की आकृतियों के रूप में मंडलियों और दीर्घवृत्तों को समझें (जैसे एक दीर्घवृत्त पर दो आकार-हैंडल, एक वृत्त पर एक हैंडल)। इसका मतलब है कि आपके पास एक दीर्घवृत्त हो सकता है जो ज्यामितीय रूप से एक चक्र है लेकिन आवेदन के दृष्टिकोण से एक सर्कल नहीं है।

  2. सर्कल सहित सभी दीर्घवृत्त का इलाज करें, लेकिन एक ही मूल्य के लिए "x" और y को "लॉक" करने का विकल्प है।

  3. एलिप्स बस ऐसे सर्कल हैं जहां स्केलिंग परिवर्तन लागू किया गया है।

प्रत्येक संभव डिज़ाइन अलग ऑब्जेक्ट मॉडल को जन्म देगा -

1 मामले में, सर्कल और एलिप्सेस भाई-बहन वर्ग होंगे

दूसरे में, एक अलग सर्कल वर्ग बिल्कुल नहीं होगा

तीसरे एक में, एक अलग एलीपस वर्ग नहीं होगा। तो तथाकथित सर्कल-एलिप्से समस्या इनमें से किसी में भी तस्वीर दर्ज नहीं करती है।

तो सवाल का जवाब देने के लिए: क्या सर्कल को दीर्घवृत्त का विस्तार करना चाहिए? इसका उत्तर है: यह इस बात पर निर्भर करता है कि आप इसके साथ क्या करना चाहते हैं। लेकिन शायद नहीं।


1
बहुत अच्छा जवाब!
उत्सव टी

6

यह "एलीप" और "सर्किल" वर्ग होने के आग्रह के लिए शुरू से एक गलती है जहां एक दूसरे का उपवर्ग है। आपके पास दो यथार्थवादी विकल्प हैं: एक के लिए अलग कक्षाएं हैं। उनके पास एक सामान्य सुपरक्लास हो सकता है, जैसे कि रंग जैसी चीजें, चाहे वह वस्तु भरी हो, ड्राइंग के लिए लाइन की चौड़ाई आदि।

दूसरे में केवल "एलीप" नाम का एक वर्ग है। यदि आपके पास वह वर्ग है, तो उसे हलकों का प्रतिनिधित्व करने के लिए इसका उपयोग करना काफी आसान है (कार्यान्वयन विवरण के आधार पर जाल हो सकते हैं; एक एलीप के पास कुछ कोण होगा और उस कोण की गणना सर्कल के आकार के दीर्घवृत्त के लिए मुसीबत में नहीं चलना चाहिए)। तुम भी परिपत्र दीर्घवृत्त के लिए विशेष तरीके हो सकता है, लेकिन इन "परिपत्र दीर्घवृत्त" अभी भी पूर्ण "Ellipse" ऑब्जेक्ट होगा।


वहाँ एक IsCircle विधि हो सकती है जो यह देखने के लिए जाँच करेगी कि क्या वास्तव में क्लास एलीप के किसी विशेष ऑब्जेक्ट में दोनों कुल्हाड़ियाँ समान हैं। आपने एंगल इश्यू भी बताया। मंडलियां 'घुमाई' नहीं जा सकतीं।

3

LSP बिंदुओं के बाद, इस समस्या का एक 'उचित' समाधान @HorusKol है और @Ixrec पर आया है - दोनों प्रकार को आकृति से प्राप्त करना। लेकिन यह उस मॉडल पर निर्भर करता है जिससे आप काम कर रहे हैं, इसलिए आपको हमेशा उसी पर वापस जाना चाहिए।

मुझे जो सिखाया गया वह है:

यदि उप-प्रकार सुपर-प्रकार के समान व्यवहार नहीं कर सकता है, तो संबंध आईएस-ए के आधार में नहीं है - इसे बदल दिया जाना चाहिए।

  • एक उप-प्रकार सुपर-प्रकार का एक सुपरसेट है।
  • एक सुपर-टाइप सब-टाइप का एक SUBSET है।

अंग्रेजी में:

  • एक व्युत्पन्न-प्रकार आधार-प्रकार का एक सुपरसेट है।
  • एक बेस-प्रकार व्युत्पन्न प्रकार का एक SUBSET है।

(उदाहरण:

  • एक बुरे लड़के के साथ एक कार अभी भी एक कार है (कुछ के अनुसार)।
  • एक इंजन, पहियों, स्टीयरिंग रैक, ड्राइवट्रेन और केवल शेल के बिना एक कार 'कार' नहीं है, यह सिर्फ एक शेल है।)

यह है कि वर्गीकरण कैसे काम करता है (यानी जानवरों की दुनिया में), और प्रिंसिपल में, ऊ में।

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

जैसा कि @HorusKul और @Ixrec द्वारा उल्लेख किया गया है, गणित में आपके पास स्पष्ट रूप से परिभाषित प्रकार हैं। लेकिन गणित में, एक सर्कल एक दीर्घवृत्त है क्योंकि यह दीर्घवृत्त का एक SUBSET है। लेकिन OOP में यह नहीं है कि वंशानुक्रम कैसे काम करता है। एक वर्ग को केवल तभी उत्तराधिकार प्राप्त करना चाहिए जब वह किसी मौजूदा वर्ग का एक सुपरसेट (विस्तार) हो - मतलब, यह अभी भी सभी संदर्भों में आधार वर्ग है।

उसके आधार पर, मुझे लगता है कि समाधान को थोड़ा प्रतिरूपित किया जाना चाहिए।

एक आकृति का आधार प्रकार है, तो Roundedhahape (प्रभावी रूप से एक चक्र है, लेकिन मैंने एक अलग नाम का उपयोग किया है यहां DELIBERATELY ...)

... फिर एलिप्से।

उस तरफ:

  • राउंडशैप एक शेप है।
  • इलिप्स एक राउंडशैप है।

(अब यह भाषा में लोगों के लिए समझ में आता है। हमारे पास पहले से ही हमारे दिमाग में एक 'सर्कल' की स्पष्ट रूप से परिभाषित अवधारणा है, और हम सामान्यीकरण (एकत्रीकरण) द्वारा यहां क्या करने की कोशिश कर रहे हैं, उस अवधारणा को तोड़ता है।)


हमारी स्पष्ट रूप से परिभाषित अवधारणाएं हमेशा अभ्यास में काम नहीं करती हैं।

-1

एक OO परिप्रेक्ष्य से दीर्घवृत्त सर्कल का विस्तार करता है, यह कुछ गुणों को जोड़कर इस पर माहिर है। सर्कल के मौजूदा गुण अभी भी दीर्घवृत्त में हैं, यह सिर्फ अधिक जटिल और अधिक विशिष्ट हो जाता है। मैं इस मामले में व्यवहार के साथ कोई समस्या नहीं देखता हूं जैसे कि Cormac करता है, आकृतियों का कोई व्यवहार नहीं है। एकमात्र परेशानी यह है कि एक भाषाई या गणितीय अर्थ में "एक दीर्घवृत्त आईएस ए सर्कल" कहना सही नहीं लगता है। क्योंकि अभ्यास के पूरे बिंदु का उल्लेख नहीं किया गया है, लेकिन फिर भी गैर-निहित है, ज्यामितीय आकृतियों को वर्गीकृत करना था। यह एक अच्छा कारण हो सकता है कि सर्कल और दीर्घवृत्त को सहकर्मी के रूप में माना जाए, न कि उन्हें विरासत से जोड़ा जाए और यह स्वीकार किया जाए कि उनके पास बस कुछ समान गुण हैं और न ही आपके मुड़ ओओ दिमाग को उस अवलोकन के साथ अपना रास्ता बनाना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.