Google ने एक ऐसे प्रश्न का उत्तर दिया, जो मुझे लगता है कि बहुत अच्छा है। मैंने इसे नीचे उद्धृत किया है।
यहाँ एक और अंतर है जो कि मेरे द्वारा जुड़े कुक निबंध में बताया गया है।
अमूर्तता को लागू करने के लिए ऑब्जेक्ट एकमात्र तरीका नहीं है। सब कुछ एक वस्तु नहीं है। ऑब्जेक्ट कुछ को लागू करते हैं, जिसे कुछ लोग प्रक्रियात्मक डेटा को अमूर्त कहते हैं। अमूर्त डेटा प्रकार अमूर्त के एक अलग रूप को लागू करते हैं।
जब आप द्विआधारी विधियों / कार्यों पर विचार करते हैं तो एक महत्वपूर्ण अंतर प्रकट होता है। प्रक्रियात्मक डेटा अमूर्त (ऑब्जेक्ट्स) के साथ, आप इंट सेट इंटरफ़ेस के लिए कुछ इस तरह लिख सकते हैं:
interface IntSet {
void unionWith(IntSet s);
...
}
अब इंसेट के दो कार्यान्वयन पर विचार करें, एक को सूचियों द्वारा समर्थित और एक जो एक अधिक कुशल बाइनरी ट्री संरचना द्वारा समर्थित है:
class ListIntSet implements IntSet {
void unionWith(IntSet s){ ... }
}
class BSTIntSet implements IntSet {
void unionWith(IntSet s){ ... }
}
ध्यान दें कि UnionWith को एक IntSet तर्क लेना चाहिए। ListIntSet या BSTIntSet जैसे अधिक विशिष्ट प्रकार नहीं। इसका मतलब यह है कि BSTIntSet कार्यान्वयन यह नहीं मान सकता है कि इसका इनपुट BSTIntSet है और एक कुशल कार्यान्वयन देने के लिए उस तथ्य का उपयोग करें। (यह जाँच करने के लिए कुछ रन टाइम टाइप की जानकारी का उपयोग कर सकता है और यदि यह है तो अधिक कुशल एल्गोरिदम का उपयोग कर सकता है, लेकिन इसे अभी भी एक ListIntSet पास किया जा सकता है और कम कुशल एल्गोरिदम में वापस आना होगा)।
इसकी तुलना ADTs से करें, जहाँ आप हस्ताक्षर या हेडर फ़ाइल में निम्नलिखित जैसे कुछ और लिख सकते हैं:
typedef struct IntSetStruct *IntSetType;
void union(IntSetType s1, IntSetType s2);
हम इस इंटरफ़ेस के खिलाफ प्रोग्राम करते हैं। विशेष रूप से, प्रकार सार छोड़ दिया गया है। आपको पता नहीं है कि यह क्या है। फिर हमारे पास एक BST कार्यान्वयन है, फिर एक ठोस प्रकार और संचालन प्रदान करता है:
struct IntSetStruct {
int value;
struct IntSetStruct* left;
struct IntSetStruct* right;
}
void union(IntSetType s1, IntSetType s2){ ... }
अब संघ वास्तव में s1 और s2 दोनों के ठोस प्रतिनिधित्व को जानता है, इसलिए यह एक कुशल कार्यान्वयन के लिए इसका फायदा उठा सकता है। हम एक सूची समर्थित कार्यान्वयन भी लिख सकते हैं और इसके बजाय लिंक करना चुन सकते हैं।
मैंने C (ish) सिंटैक्स लिखा है, लेकिन आपको यह देखना चाहिए कि अमूर्त डेटा प्रकारों के लिए Standard ML ठीक प्रकार से किया गया है (जहाँ आप उदाहरण के लिए एक प्रोग्राम में ADT के एक से अधिक कार्यान्वयन का उपयोग कर सकते हैं। IntSetStruct और ListImpl.IntSetStruct, कहते हैं)
इसका संकेत यह है कि प्रक्रियात्मक डेटा अमूर्त (ऑब्जेक्ट्स) आपको आसानी से नए कार्यान्वयन लागू करने की अनुमति देता है जो आपके पुराने लोगों के साथ काम करते हैं। उदाहरण के लिए, आप अपने स्वयं के कस्टम LoggingIntSet कार्यान्वयन को लिख सकते हैं, और इसे BSTIntSet के साथ जोड़ सकते हैं। लेकिन यह एक व्यापार है: आप द्विआधारी तरीकों के लिए जानकारीपूर्ण प्रकार खो देते हैं! अक्सर आप एक ADT कार्यान्वयन के साथ अपने इंटरफ़ेस में अधिक कार्यक्षमता और कार्यान्वयन विवरणों को उजागर करने के लिए समाप्त होते हैं। अब मुझे ऐसा लग रहा है कि मैं सिर्फ कुक निबंध को पुनः लिख रहा हूँ, इसलिए वास्तव में, इसे पढ़ें!
मैं इसका एक उदाहरण जोड़ना चाहूंगा।
कुक सुझाव देते हैं कि अमूर्त डेटा प्रकार का एक उदाहरण सी में एक मॉड्यूल है। सी में मॉड्यूल, जानकारी को छिपाने में शामिल हैं, क्योंकि सार्वजनिक कार्य हैं जो हेडर फ़ाइल के माध्यम से निर्यात किए जाते हैं, और स्थिर (निजी) फ़ंक्शन नहीं होते हैं। इसके अतिरिक्त, अक्सर कंस्ट्रक्टर होते हैं (जैसे list_new ()) और ऑब्जर्वर (जैसे list_getListHead ())।
ADT क्या बनाता है, कहते हैं, एक सूची मॉड्यूल जिसे LIST_MODULE_SINGLY_LINK ने ADT कहा है, मॉड्यूल के कार्य (जैसे list_getListHead ()) यह मानते हैं कि इनपुट किया जा रहा डेटा LIST_MODULE_SINGLY_LINKED के निर्माता द्वारा बनाया गया है, किसी भी समतुल्य के विपरीत। "एक सूची का कार्यान्वयन (जैसे LIST_MODULE_DYNAMIC_ARRAY)। इसका अर्थ है कि LIST_MODULE_SINGLY_LINKED के कार्य, उनके कार्यान्वयन में, एक विशेष प्रतिनिधित्व (जैसे एक एकल लिंक की गई सूची) मान सकते हैं।
LIST_MODULE_SINGLY_LINKED LIST_MODULE_DYNAMIC_ARRAY के साथ काम नहीं कर सकता क्योंकि हम बनाए गए डेटा को फ़ीड नहीं कर सकते, LIST_MODULE_AMODIC_ARRAY के लिए पर्यवेक्षक के रूप में LIST_MODULE_DYNAMIC_ARRAY के साथ काम नहीं कर सकते, क्योंकि यह LIST_MODULE_DYNAMIC_ARRAY के कारण नहीं है।
यह एक तरह से अनुरूप है कि अमूर्त बीजगणित से दो अलग-अलग समूह आपस में जुड़ नहीं सकते हैं (अर्थात, आप एक समूह के एक तत्व के उत्पाद को दूसरे समूह के तत्व के साथ नहीं ले सकते हैं)। ऐसा इसलिए है क्योंकि समूह समूह की बंद संपत्ति मानते हैं (समूह में तत्वों का उत्पाद समूह में होना चाहिए)। हालांकि, अगर हम यह साबित कर सकते हैं कि दो अलग-अलग समूह वास्तव में दूसरे समूह G के उपसमूहों में हैं, तो हम G के उत्पाद का उपयोग दो तत्वों में से एक, दो समूहों में से एक को जोड़ने के लिए कर सकते हैं।
एडीटी और वस्तुओं की तुलना करना
कुक ADTs और ऑब्जेक्ट्स के बीच अंतर को आंशिक रूप से अभिव्यक्ति समस्या के रूप में रखता है। मोटे तौर पर, एडीटी सामान्य कार्यों के साथ युग्मित होते हैं जो अक्सर कार्यात्मक प्रोग्रामिंग भाषाओं में लागू होते हैं, जबकि ऑब्जेक्ट्स को इंटरफेस के माध्यम से एक्सेस किए गए जावा "ऑब्जेक्ट्स" के साथ युग्मित किया जाता है। इस पाठ के प्रयोजनों के लिए, एक सामान्य कार्य एक फ़ंक्शन है जो कुछ तर्क ARGS और एक प्रकार TYPE (पूर्व-स्थिति) में लेता है; TYPE के आधार पर यह उपयुक्त फ़ंक्शन का चयन करता है, और ARGS (पोस्ट-कंडीशन) के साथ इसका मूल्यांकन करता है। जेनेरिक फ़ंक्शंस और ऑब्जेक्ट दोनों बहुरूपता को लागू करते हैं, लेकिन जेनेरिक फ़ंक्शंस के साथ, प्रोग्रामर KNOWS जो जेनेरिक फ़ंक्शन के कोड को देखे बिना जेनेरिक फ़ंक्शन द्वारा निष्पादित किया जाएगा। दूसरी ओर वस्तुओं के साथ, प्रोग्रामर को यह नहीं पता होता है कि ऑब्जेक्ट कैसे तर्कों को हैंडल करेगा, जब तक कि प्रोग्रामर ऑब्जेक्ट के कोड को नहीं देखता है।
आमतौर पर अभिव्यक्ति की समस्या के बारे में सोचा जाता है "क्या मेरे पास बहुत सारे प्रतिनिधित्व हैं?" बनाम "क्या मुझे कुछ प्रतिनिधित्व के साथ बहुत सारे कार्य हैं"। पहले मामले में किसी को प्रतिनिधित्व द्वारा कोड व्यवस्थित करना चाहिए (जैसा कि सबसे आम है, खासकर जावा में)। दूसरे मामले में एक को फ़ंक्शन द्वारा कोड व्यवस्थित करना चाहिए (यानी एक एकल सामान्य फ़ंक्शन को कई अभ्यावेदन संभालना)।
यदि आप अपने कोड को प्रतिनिधित्व द्वारा व्यवस्थित करते हैं, तो, यदि आप अतिरिक्त कार्यक्षमता जोड़ना चाहते हैं, तो आपको ऑब्जेक्ट के प्रत्येक प्रतिनिधित्व के लिए कार्यक्षमता जोड़ने के लिए मजबूर किया जाता है; इस अर्थ में कार्यक्षमता जोड़ना "योगात्मक" नहीं है। यदि आप कार्यक्षमता द्वारा अपना कोड व्यवस्थित करते हैं, तो, यदि आप एक अतिरिक्त प्रतिनिधित्व जोड़ना चाहते हैं - तो आपको प्रत्येक ऑब्जेक्ट में प्रतिनिधित्व जोड़ने के लिए मजबूर किया जाता है; इस अर्थ में "योगात्मक" नहीं है।
वस्तुओं पर ADTs का लाभ
कार्यक्षमता जोड़ना योगात्मक है
प्रदर्शन के लिए एक एडीटी के प्रतिनिधित्व के ज्ञान का लाभ उठाने के लिए संभव है, या यह साबित करने के लिए कि एडीटी एक पूर्व शर्त दिए गए कुछ पोस्टकंडिशन की गारंटी देगा। इसका मतलब यह है कि एडीटी के साथ प्रोग्रामिंग सही क्रम में सही काम करने के बारे में है ("लक्ष्य" पोस्ट की स्थिति के लिए पूर्व-शर्तों और पोस्ट-शर्तों को एक साथ जोड़ते हुए)।
ADTs पर वस्तुओं का लाभ
Additive में अभ्यावेदन जोड़ना
वस्तुएं आपस में जुड़ सकती हैं
किसी ऑब्जेक्ट के लिए पूर्व / पोस्ट की शर्तों को निर्दिष्ट करना संभव है, और इनको एक साथ मिलाएं जैसा कि ADTs के साथ होता है। इस स्थिति में, वस्तुओं के फायदे यह हैं कि (1) इंटरफ़ेस को बदलने के बिना अभ्यावेदन को बदलना आसान है और (2) ऑब्जेक्ट अंतर-ऑपरेट कर सकते हैं। हालाँकि, यह OOP के उद्देश्य को स्मालटाक के अर्थ में पराजित करता है। (देखें अनुभाग "एलन के के OOP का संस्करण)
डायनेमिक प्रेषण OOP की कुंजी है
अब यह स्पष्ट होना चाहिए कि वस्तु उन्मुख प्रोग्रामिंग के लिए डायनामिक डिस्पैच (यानी देर से बाध्यकारी) आवश्यक है। ऐसा इसलिए है कि प्रक्रियाओं को एक सामान्य तरीके से परिभाषित करना संभव है, जो किसी विशेष प्रतिनिधित्व को ग्रहण नहीं करता है। ठोस होने के लिए - ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग अजगर में आसान है, क्योंकि किसी ऑब्जेक्ट के तरीकों को इस तरह से प्रोग्राम करना संभव है जो किसी विशेष प्रतिनिधित्व को ग्रहण नहीं करता है। यही कारण है कि अजगर को जावा जैसे इंटरफेस की आवश्यकता नहीं है।
जावा में, कक्षाएं एडीटी हैं। हालाँकि, इंटरफ़ेस के माध्यम से एक वर्ग जिस पर लागू होता है वह एक वस्तु है।
परिशिष्ट: एलन Kay OOP का संस्करण
एलन के ने स्पष्ट रूप से वस्तुओं को "बीजगणित के परिवार" के रूप में संदर्भित किया है, और कुक का सुझाव है कि एक एडीटी एक बीजगणित है। इसलिए Kay का अर्थ है कि एक वस्तु ADTs का एक परिवार है। यही है, एक ऑब्जेक्ट सभी वर्गों का संग्रह है जो एक जावा इंटरफ़ेस को संतुष्ट करता है।
हालांकि, कुक द्वारा चित्रित वस्तुओं की तस्वीर एलन के की दृष्टि से कहीं अधिक प्रतिबंधात्मक है। वह वस्तुओं को एक नेटवर्क में कंप्यूटर के रूप में, या जैविक कोशिकाओं के रूप में व्यवहार करना चाहता था। यह विचार था कि प्रोग्रामिंग के लिए कम से कम प्रतिबद्धता के सिद्धांत को लागू किया जाए - ताकि एक एडीटी के निम्न स्तर की परतों को बदलना आसान हो जाए क्योंकि एक बार उच्च स्तरीय परतों का उपयोग करके बनाया गया है। इस तस्वीर को ध्यान में रखते हुए, जावा इंटरफेस बहुत अधिक प्रतिबंधात्मक हैं क्योंकि वे किसी वस्तु को संदेश के अर्थ की व्याख्या करने की अनुमति नहीं देते हैं , या यहां तक कि इसे पूरी तरह से अनदेखा करते हैं।
संक्षेप में, Kay के लिए वस्तुओं का मुख्य विचार - यह नहीं है कि वे बीजगणित के परिवार हैं (जैसा कि कुक द्वारा जोर दिया गया है)। बल्कि, Kay का मुख्य विचार एक मॉडल लागू करना था जो बड़े (एक नेटवर्क में कंप्यूटर) में छोटे (एक प्रोग्राम में ऑब्जेक्ट) में काम करता था।
संपादित करें: Kay के OOP के संस्करण पर एक और स्पष्टीकरण: वस्तुओं का उद्देश्य एक घोषणात्मक आदर्श के करीब जाना है। हमें ऑब्जेक्ट को यह बताना चाहिए कि क्या करना है - यह नहीं बताएं कि माइक्रोमैनेजिंग कैसे राज्य है, जैसा कि प्रक्रियात्मक प्रोग्रामिंग और एडीटी के साथ प्रथागत है। अधिक जानकारी यहाँ , यहाँ , यहाँ , और यहाँ मिल सकती है ।
संपादित करें: मुझे एलन कय की OOP की परिभाषा का एक बहुत अच्छा प्रदर्शन यहां मिला ।