क्या पायथन की विरासत "एक" विरासत की शैली या एक रचना शैली है?


10

यह देखते हुए कि पायथन कई विरासतों के लिए अनुमति देता है, पायथन में मुहावरेदार विरासत क्या दिखती है?

जावा की तरह एकल वंशानुक्रम वाली भाषाओं में, वंशानुक्रम का उपयोग तब किया जाएगा जब आप कह सकते हैं कि एक वस्तु "किसी अन्य वस्तु का" है और आप वस्तुओं के बीच कोड साझा करना चाहते हैं (मूल वस्तु से बच्चे की वस्तु तक)। उदाहरण के लिए, आप कह सकते हैं कि Dogएक है Animal:

public class Animal {...}
public class Dog extends Animal {...}

लेकिन चूंकि पायथन एकाधिक वंशानुक्रम का समर्थन करता है इसलिए हम एक साथ कई अन्य वस्तुओं की रचना करके एक वस्तु बना सकते हैं। नीचे दिए गए उदाहरण पर विचार करें:

class UserService(object):
    def validate_credentials(self, username, password):
        # validate the user credentials are correct
        pass


class LoggingService(object):
    def log_error(self, error):
        # log an error
        pass


class User(UserService, LoggingService):
    def __init__(self, username, password):
        self.username = username
        self.password = password

    def authenticate(self):
        if not super().validate_credentials(self.username, self.password):
            super().log_error('Invalid credentials supplied')
            return False
         return True

क्या यह पायथन में कई वंशानुक्रम का स्वीकार्य या अच्छा उपयोग है? इसके बजाय कह की विरासत है जब एक वस्तु "है-एक" एक और वस्तु की, हम एक बनाने है Userमॉडल से बना UserServiceऔर LoggingService

डेटाबेस या नेटवर्क संचालन के लिए सभी तर्क Userको UserServiceऑब्जेक्ट में रखकर मॉडल से अलग रखा जा सकता है और लॉग इन करने के लिए सभी तर्क रखे जा सकते हैं LoggingService

मैं इस दृष्टिकोण के साथ कुछ समस्याएं देख रहा हूं:

  • क्या यह एक ईश्वर वस्तु बनाता है? चूंकि Userविरासत में मिली है, या इससे बना है, UserServiceऔर LoggingServiceक्या यह वास्तव में एकल जिम्मेदारी के सिद्धांत का पालन कर रहा है?
  • माता-पिता / अगली-इन-लाइन ऑब्जेक्ट पर विधियों तक पहुंचने के लिए (जैसे, UserService.validate_credentialsहमें superइसका उपयोग करना होगा । इससे यह देखना थोड़ा अधिक कठिन हो जाता है कि कौन सी वस्तु इस विधि को संभालने जा रही है और जैसा कि स्पष्ट नहीं है, कहते हैं , तुरंत UserServiceऔर कुछ करना पसंद हैself.user_service.validate_credentials

उपरोक्त कोड को लागू करने का पाइथोनिक तरीका क्या होगा?

जवाबों:


9

क्या पायथन की विरासत "एक" विरासत की शैली या एक रचना शैली है?

अजगर दोनों शैलियों का समर्थन करता है। आप संरचना के संबंध का प्रदर्शन कर रहे हैं, जहां उपयोगकर्ता के पास एक स्रोत से लॉगिंग कार्यक्षमता और दूसरे स्रोत से क्रेडेंशियल सत्यापन है। LoggingServiceऔर UserServiceठिकानों mixins हैं: वे कार्यक्षमता प्रदान और खुद से instantiated करने के लिए लक्षित नहीं हैं।

प्रकार में मिश्रणों की रचना करके, आपके पास एक उपयोगकर्ता है जो लॉग इन कर सकता है, लेकिन जिसे अपनी त्वरित कार्यक्षमता को जोड़ना होगा।

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

क्या यह एक ईश्वर वस्तु बनाता है?

लॉगिंग कुछ हद तक मूर्त लगती है - पायथन में एक लॉगर ऑब्जेक्ट के साथ अपना लॉगिंग मॉड्यूल होता है, और कन्वेंशन यह है कि प्रति मॉड्यूल एक लॉगर है।

लेकिन लॉगिंग मॉड्यूल को अलग सेट करें। शायद यह एकल-जिम्मेदारी का उल्लंघन करता है, लेकिन शायद, आपके विशिष्ट संदर्भ में, उपयोगकर्ता को परिभाषित करना महत्वपूर्ण है। विवेकी जिम्मेदारी विवादास्पद हो सकती है। लेकिन व्यापक सिद्धांत यह है कि पायथन उपयोगकर्ता को निर्णय लेने की अनुमति देता है।

सुपर कम स्पष्ट है?

superकेवल तभी आवश्यक है जब आपको उसी नाम के एक फ़ंक्शन के अंदर से विधि रिज़ॉल्यूशन ऑर्डर (MRO) में एक माता-पिता को सौंपने की आवश्यकता हो। माता-पिता की विधि के लिए कॉल को हार्ड-कोडिंग के बजाय इसका उपयोग करना सबसे अच्छा अभ्यास है। लेकिन अगर आप माता-पिता को हार्ड-कोड करने नहीं जा रहे हैं, तो आपको ज़रूरत नहीं है super

यहां आपके उदाहरण में, आपको केवल करने की आवश्यकता है self.validate_credentialsselfआपके दृष्टिकोण से, अधिक स्पष्ट नहीं है। वे दोनों एमआरओ का पालन करते हैं। मैं बस जहां उचित होगा प्रत्येक का उपयोग करेगा।

यदि आपने कॉल किया था authenticate, तो validate_credentialsइसके बजाय, आपको superपुनरावृत्ति त्रुटि से बचने के लिए (या माता-पिता को हार्ड-कोड) का उपयोग करने की आवश्यकता होगी ।

वैकल्पिक कोड सुझाव

इसलिए, शब्दार्थ को ठीक मानते हैं (जैसे लॉगिंग), मैं कक्षा में क्या करूंगा User:

    def validate_credentials(self): # changed from "authenticate" to 
                                    # demonstrate need for super
        if not super().validate_credentials(self.username, self.password):
            # just use self on next call, no need for super:
            self.log_error('Invalid credentials supplied') 
            return False
        return True

1
मैं असहमत हूं। वंशानुक्रम हमेशा अपने उपवर्गों में एक वर्ग के सार्वजनिक इंटरफ़ेस की एक प्रति बनाता है। यह एक "संबंध नहीं है" है। यह सबटाइपिंग, सादा और सरल है, और इसलिए वर्णित एप्लिकेशन के लिए अनुचित है।
जूल्स

@ जूल्स आप किस बात से असहमत हैं? मैंने बहुत सी बातें कही हैं जो प्रदर्शनकारी हैं, और निष्कर्ष निकाला है जो तार्किक रूप से अनुसरण करते हैं। आप कर रहे हैं जब आप कहते हैं, गलत "विरासत हमेशा अपने उपवर्गों में एक वर्ग के सार्वजनिक इंटरफ़ेस एक कॉपी बन जाती।" पायथन में, कोई प्रतिलिपि नहीं है - सी 3 एल्गोरिथ्म विधि संकल्प आदेश (एमआरओ) के अनुसार विधियों को गतिशील रूप से देखा जाता है।
एरॉन हॉल

1
यह बात विशिष्ट विवरण के बारे में नहीं है कि कार्यान्वयन कैसे काम करता है, यह इस बारे में है कि वर्ग का सार्वजनिक इंटरफ़ेस कैसा दिखता है। उदाहरण के मामले में, Userवस्तुओं उनके इंटरफेस न केवल सदस्यों में परिभाषित में है Userवर्ग, लेकिन यह भी लोगों में परिभाषित किया गया UserServiceऔर LoggingService। यह नहीं है एक "है-एक" रिश्ता है, क्योंकि सार्वजनिक इंटरफेस (नहीं प्रत्यक्ष नकल के माध्यम से, बल्कि सुपर-क्लास 'इंटरफेस के एक अप्रत्यक्ष देखने से हालांकि) की नकल की है।
जूल्स

हैस का एक साधन है। मिश्रण एक रचना का रूप है। उपयोगकर्ता वर्ग है एक UserService या LoggingService नहीं है, लेकिन यह है कि कार्यक्षमता। मुझे लगता है कि पायथन की विरासत जावा की तुलना में अधिक भिन्न है, जितना आपको एहसास है।
आरोन हॉल

@AaronHall आप अति-सरल कर रहे हैं (यह आपको अन्य उत्तर का विरोध करता है , जो मुझे संयोग से मिला)। उपप्रकार संबंध के दृष्टिकोण से, एक उपयोगकर्ता एक उपयोगकर्ता सेवा और एक लॉगिंग सेवा दोनों है। अब, यहाँ आत्मा कार्यात्मकताओं की रचना करने के लिए है ताकि एक उपयोगकर्ता के पास ऐसी और कार्यात्मकताएँ हों। सामान्य रूप से मिश्रणों को कई-विरासत के साथ लागू करने की आवश्यकता नहीं होती है। हालाँकि यह पायथन में ऐसा करने का सामान्य तरीका है।
coredump

-1

इस तथ्य के अलावा कि यह कई सुपरक्लेसेस की अनुमति देता है, पायथन की विरासत जावा के लिए पर्याप्त रूप से भिन्न नहीं है, यानी एक उपवर्ग के सदस्य भी उनके प्रत्येक सुपरटेप्स [1] के सदस्य हैं। यह तथ्य कि पायथन डक-टाइपिंग का उपयोग करता है, इससे कोई फर्क नहीं पड़ता: आपके उपवर्ग में इसके सभी सुपरक्लास के सभी सदस्य हैं, इसलिए किसी भी कोड का उपयोग करने में सक्षम है जो उन उपवर्गों का उपयोग कर सकता है। तथ्य यह है कि संरचना का उपयोग करके कई विरासत को प्रभावी ढंग से लागू किया जाता है एक लाल हेरिंग है: कि एक वर्ग से दूसरे वर्ग के गुणों की स्वचालित नकल मुद्दा है, और इससे कोई फर्क नहीं पड़ता कि यह रचना का उपयोग करता है या सिर्फ जादुई अनुमान लगाता है कि सदस्यों को कैसे माना जाता है काम करना: उनका होना गलत है।

हां, यह एकल जिम्मेदारी का उल्लंघन करता है, क्योंकि आप अपनी वस्तुओं को उन कार्यों को करने की क्षमता दे रहे हैं जो तार्किक रूप से उस भाग का हिस्सा नहीं हैं जो वे करने के लिए डिज़ाइन किए गए हैं। हां, यह "भगवान" वस्तुओं का निर्माण करता है, जो अनिवार्य रूप से एक ही बात कहने का एक और तरीका है।

पायथन में ऑब्जेक्ट-ओरिएंटेड सिस्टम को डिजाइन करते समय, जावा डिजाइन की पुस्तकों द्वारा प्रचारित वही अधिकतम लागू होता है: विरासत के लिए रचना पसंद करते हैं। एक ही (अधिकांश [2]) अन्य व्यवस्थाओं के साथ एक ही सच है।

[१]: आप कह सकते हैं कि "ए-ए" रिलेशनशिप है, हालांकि मुझे व्यक्तिगत रूप से यह शब्द पसंद नहीं है क्योंकि यह वास्तविक दुनिया को मॉडलिंग करने का विचार बताता है, और ऑब्जेक्ट ओरिएंटेड मॉडलिंग वास्तविक दुनिया के समान नहीं है।

[२]: मैं सी ++ के बारे में इतना निश्चित नहीं हूं। C ++ "निजी विरासत" का समर्थन करता है जो अनिवार्य रूप से एक क्षेत्र का नाम निर्दिष्ट करने की आवश्यकता के बिना है जब आप विरासत में मिले वर्ग के सार्वजनिक सदस्यों का उपयोग करना चाहते हैं। यह कक्षा के सार्वजनिक इंटरफ़ेस को बिल्कुल भी प्रभावित नहीं करता है। मुझे इसका उपयोग करना पसंद नहीं है, लेकिन मैं कोई भी अच्छा कारण नहीं देख सकता।

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