अधिक भार? हाँ या नहीं [बंद]


17

मैं एक वैधानिक रूप से विकसित कर रहा हूं- और दृढ़ता से टाइप की गई, संकलित भाषा, और मैं इस विचार पर फिर से विचार कर रहा हूं कि क्या फ़ंक्शन ओवरलोडिंग को एक भाषा सुविधा के रूप में शामिल करना है या नहीं। मुझे एहसास हुआ कि मैं थोड़ा सा पक्षपाती हूं, मुख्यतः C[++|#]पृष्ठभूमि से।

सबसे विश्वसनीय तर्क क्या हैं के लिए और के खिलाफ एक भाषा में अधिक भार समारोह सहित?


संपादित करें: क्या कोई भी ऐसा नहीं है जिसका विरोधी राय है?

बर्ट्रेंड मेयर (1985/1986 में एफिल बैक के निर्माता) इसे ओवरलोड करने की विधि कहते हैं: (स्रोत)

एक घमंड तंत्र जो एक OO भाषा की शब्दार्थ शक्ति को कुछ नहीं लाता है, लेकिन पठनीयता को बाधित करता है और हर किसी के कार्य को जटिल बनाता है

अब वे कुछ व्यापक सामान्यीकरण हैं, लेकिन वह एक स्मार्ट लड़का है, इसलिए मुझे लगता है कि यह कहना सुरक्षित है कि यदि आवश्यक हो तो वह उन्हें वापस कर सकता है। वास्तव में, उनके पास ब्रैड अब्राम्स (CLSv1 डेवलपर्स में से एक) था, ने आश्वस्त किया कि .NET को ओवरलोडिंग की विधि का समर्थन नहीं करना चाहिए। (स्रोत) यह कुछ शक्तिशाली सामग्री है। क्या कोई अपने विचारों पर कुछ प्रकाश डाल सकता है, और क्या उसका दृष्टिकोण 25 साल बाद भी उचित है?

जवाबों:


24

फंक्शन ओवरलोडिंग C ++ शैली टेम्पलेट कोड के लिए बिल्कुल महत्वपूर्ण है। अगर मुझे विभिन्न प्रकारों के लिए विभिन्न फ़ंक्शन नामों का उपयोग करना है, तो मैं सामान्य कोड नहीं लिख सकता। यह C ++ लाइब्रेरी के एक बड़े और भारी उपयोग वाले भाग को समाप्त कर देगा, और C ++ की कार्यक्षमता का अधिकांश भाग।

यह आमतौर पर सदस्य फ़ंक्शन नामों में मौजूद होता है। A.foo()से एक पूरी तरह से अलग कार्य कह सकते हैं B.foo(), लेकिन दोनों कार्यों के नाम हैं foo। यह ऑपरेटरों में मौजूद है, जैसा +कि पूर्णांक और फ्लोटिंग-पॉइंट संख्याओं पर लागू होने पर अलग-अलग चीजें होती हैं, और यह अक्सर स्ट्रिंग कॉन्फ्रेनेशन ऑपरेटर के रूप में उपयोग किया जाता है। नियमित कार्यों में भी इसकी अनुमति नहीं देना अजीब लगता है।

यह कॉमन लिस्प-शैली "मल्टीमिथोड्स" के उपयोग को सक्षम करता है, जिसमें सटीक फ़ंक्शन कहा जाता है जो दो डेटा प्रकारों पर निर्भर करता है। यदि आपने सामान्य लिस्प ऑब्जेक्ट सिस्टम में प्रोग्राम नहीं किया है, तो इसे बेकार कहने से पहले इसे आज़माएं। यह C ++ स्ट्रीम के लिए महत्वपूर्ण है।

I / O बिना फ़ंक्शन ओवरलोडिंग के (या वैरेडिक फ़ंक्शंस, जो बदतर हैं) कई अलग-अलग फ़ंक्शंस की आवश्यकता होगी, या तो विभिन्न प्रकारों के मूल्यों को प्रिंट करने के लिए या विभिन्न प्रकारों के मूल्यों को एक सामान्य प्रकार (जैसे स्ट्रिंग) में परिवर्तित करने के लिए।

फंक्शन ओवरलोडिंग के बिना, अगर मैं कुछ वैरिएबल या वैल्यू के प्रकार को बदलता हूं तो मुझे इसके उपयोग करने वाले हर फंक्शन को बदलना होगा। यह कोडक को रिफलेक्टर करने के लिए बहुत कठिन बनाता है।

यह एपीआई का उपयोग करना आसान बनाता है जब उपयोगकर्ता को यह याद नहीं रखना पड़ता है कि किस प्रकार का नामकरण सम्मेलन उपयोग में है, और उपयोगकर्ता बस मानक फ़ंक्शन नामों को याद रख सकता है।

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

कुल मिलाकर, यह एक भाषा को अधिक उपयोगी बनाता है।


1
+1, सभी बहुत अच्छे अंक। और मुझ पर विश्वास करो, मुझे नहीं लगता कि मल्टीमिथोड बेकार हैं ... मैं बहुत ही कीबोर्ड को शाप देता हूं जो मुझे हर बार आगंतुक पैटर्न का उपयोग करने के लिए मजबूर किया जाता है।
स्वयं पर ध्यान दें -

क्या यह आदमी ओवरराइडिंग का कार्य नहीं कर रहा है और न ही ओवरलोडिंग का वर्णन कर रहा है?
ड्रैगसॉब

8

मैं कम से कम हास्केल में टाइप कक्षाओं से अवगत होने की सलाह देता हूं। टाइप क्लास को ऑपरेटर ओवरलोडिंग के लिए एक अनुशासित दृष्टिकोण के रूप में बनाया गया था, लेकिन अन्य उपयोगों को पाया है, और एक हद तक, हास्केल को बनाया है।

उदाहरण के लिए, यहाँ तदर्थ अधिभार (काफी मान्य हास्केल नहीं) का एक उदाहरण दिया गया है:

(==) :: Int -> Int -> Bool
x == y = ...
x /= y = not (x == y)

(==) :: Char -> Char -> Bool
x == y = ...
x /= y = not (x == y)

और यहाँ प्रकार वर्गों के साथ ओवरलोडिंग का एक ही उदाहरण है:

class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool

    x /= y  =  not (x == y)

instance Eq Int where
    x == y  = ...

instance Eq Char where
    x == y  = ...

इस का एक नकारात्मक पक्ष यह है कि आप अपने सभी typeclasses के लिए फैशनेबल नामों के साथ आने के लिए है कि है (हास्केल में की तरह, आप के बजाय सार है Monad, Functor, Applicativeऔर साथ ही सरल और अधिक पहचानने योग्य Eq, Numऔर Ord)।

एक उल्टा यह है कि, एक बार जब आप एक टाइपकास्ट से परिचित हो जाते हैं, तो आप जानते हैं कि उस कक्षा में किसी भी प्रकार का उपयोग कैसे करें। इसके अलावा, प्रकारों से कार्यों की रक्षा करना आसान है जो आवश्यक वर्गों को लागू नहीं करते हैं, जैसे:

group :: (Eq a) => [a] -> [[a]]
group = groupBy (==)

संपादित करें: हास्केल में, यदि आप एक ==ऑपरेटर चाहते हैं जो दो अलग-अलग प्रकारों को स्वीकार करता है, तो आप एक बहु-पैरामीटर प्रकार वर्ग का उपयोग कर सकते हैं:

class Eq a b where
    (==) :: a -> b -> Bool
    (/=) :: a -> b -> Bool

    x /= y  =  not (x == y)

instance Eq Int Int where
    x == y  = ...

instance Eq Char Char where
    x == y  = ...

instance Eq Int Float where
    x == y  = ...

बेशक, यह शायद एक बुरा विचार है, क्योंकि यह स्पष्ट रूप से आपको सेब और संतरे की तुलना करने देता है। हालाँकि, आप इस पर विचार करना चाह सकते हैं +, क्योंकि कुछ संदर्भों में वास्तव में जोड़ने के Word8लिए Intएक समझदार चीज है।


+1, मैं इस अवधारणा को समझने की कोशिश कर रहा हूं क्योंकि मैंने पहली बार इसे पढ़ा है, और यह मदद करता है। क्या इस प्रतिमान को परिभाषित करना असंभव है, उदाहरण के लिए, (==) :: Int -> Float -> Boolकहीं भी? (चाहे यह एक अच्छा विचार है, निश्चित रूप से)
स्वयं पर ध्यान दें -

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

हां दिलचस्प। इसलिए मूल रूप से, class Eq a ...छद्म-सी-परिवार में अनुवाद किया जाता है interface Eq<A> {bool operator==(A x, A y);}, और मनमानी वस्तुओं की तुलना करने के लिए टेम्पर्ड कोड का उपयोग करने के बजाय, आप इस 'इंटरफ़ेस' का उपयोग करते हैं। क्या वह सही है?
स्वयं पर ध्यान दें -

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

1
@ Notetoself-thinkofaname: अतिरिक्त ऑपरेटरों के बारे में - हां और नहीं। यह ==एक अलग नाम-स्थान में रहने की अनुमति देता है लेकिन इसे ओवरराइड करने की अनुमति नहीं देता है। कृपया ध्यान दें कि एक एकल नाम स्थान ( Prelude) डिफ़ॉल्ट रूप से शामिल है, लेकिन आप इसे एक्सटेंशन का उपयोग करके या इसे स्पष्ट रूप से आयात करने से रोक सकते हैं ( वर्तमान नामस्थान में प्रतीकों को सम्मिलित नहीं करेंगे और import Prelude ()कुछ भी आयात नहीं करेंगे)। Preludeimport qualified Prelude as P
मैकीज पीचोटका

4

फ़ंक्शन को ओवरलोडिंग की अनुमति दें, आप वैकल्पिक मापदंडों के साथ निम्नलिखित नहीं कर सकते हैं (या यदि आप कर सकते हैं, तो अच्छी तरह से नहीं)।

तुच्छ उदाहरण कोई विधि नहीं मानता हैbase.ToString()

string ToString(int i) {}
string ToString(double d) {}
string ToString(DateTime d) {}
...

जोरदार टाइप की गई भाषा के लिए, हाँ। कमजोर टाइप की भाषा के लिए, नहीं। आप कमजोर टाइप की गई भाषा में केवल एक ही कार्य कर सकते हैं।
20

2

मैं हमेशा फ़ंक्शन ओवरलोडिंग पर डिफ़ॉल्ट मापदंडों को प्राथमिकता देता हूं। ओवरलोड कार्यों को आम तौर पर डिफ़ॉल्ट मापदंडों के साथ "डिफ़ॉल्ट" संस्करण कहते हैं। क्यों लिखते हैं?

int indexOf(char ch)
{
  return self.indexOf(ch, 0);
}

int indexOf(char ch, int fromIndex)
{
  // Do whatever
}

जब मैं कर सकता था:

int indexOf(char ch, int fromIndex=0)
{
  // Do whatever
}

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

(इसके अलावा, पायथन-शैली कीवर्ड तर्क डिफ़ॉल्ट मापदंडों के साथ वास्तव में अच्छी तरह से काम करते हैं।)


ठीक है, चलो फिर से कोशिश करते हैं, और मैं इस बार समझ बनाने की कोशिश करूँगा ... क्या Array Slice(int start, int length) {...}अतिभारित है Array Slice(int start) {return this.Slice(start, this.Count - start);}? यह डिफ़ॉल्ट पैरामीटर का उपयोग करके कोडित नहीं किया जा सकता है। क्या आपको लगता है कि उन्हें अलग नाम दिया जाना चाहिए? यदि हां, तो आप उनका नाम कैसे लेंगे?
स्वयं पर ध्यान दें -

यह ओवरलोडिंग के सभी उपयोगों को संबोधित नहीं करता है।
MetalMikester

@MetalMikester: आपको क्या लगता है कि मैं चूक गया?
मियादी

@mipadi यह एक सूची में indexOf(char ch)+ जैसी चीजों को याद करता है indexOf(Date dt)। मुझे डिफ़ॉल्ट मान भी पसंद हैं लेकिन वे स्थिर टाइपिंग के साथ विनिमेय नहीं हैं।
मार्क

2

आपने अभी जावा का वर्णन किया है। या सी #।

आप पहिया को क्यों रोक रहे हैं?

सुनिश्चित करें कि वापसी प्रकार विधि हस्ताक्षर का हिस्सा है और आपके दिल की सामग्री को अधिभार देता है, यह वास्तव में कोड को साफ करता है जब आपको कहना नहीं पड़ता है।

function getThisFirstWay(int type)
{ ... }
function getThisSecondWay(int type, double limit)
{ ... }
function getThisThirdWay(int type, String match)
{ ... }

7
एक कारण है कि रिटर्न प्रकार विधि हस्ताक्षर का हिस्सा नहीं है - या कम से कम ऐसा हिस्सा नहीं है जिसका उपयोग अधिभार संकल्प के लिए किया जा सकता है - किसी भी भाषा में जिसके बारे में मुझे पता है। जब आप एक फ़ंक्शन को एक प्रक्रिया के रूप में कहते हैं, तो चर या संपत्ति के परिणाम को बताए बिना, कंपाइलर को यह पता लगाने की आवश्यकता है कि यदि सभी अन्य तर्क समान हैं तो किस संस्करण को लागू करना है?
मेसन व्हीलर

@ मेसन: आप उत्तराधिकारी को लौटाए जाने की उम्मीद के आधार पर अपेक्षित रिटर्न प्रकार का पता लगा सकते हैं, हालाँकि मुझे उम्मीद नहीं है कि ऐसा किया जाएगा।
जोश के

1
उम्म ... आपकी हेयुरिस्टिक को कैसे पता चलता है कि जब आप किसी रिटर्न वैल्यू की उम्मीद नहीं कर रहे हैं तो क्या लौटाया जाना चाहिए?
मेसन व्हीलर

1
प्रकार-प्रत्याशा अनुमानी वास्तव में जगह में है ... आप जैसे काम कर सकते हैं EnumX.Flag1 | Flag2 | Flag3। मैं इसे लागू नहीं करूंगा, हालांकि। अगर मैंने किया और वापसी प्रकार का उपयोग नहीं किया गया था, तो मैं वापसी प्रकार की तलाश करूंगा void
स्वयं पर ध्यान दें -

1
@ मेसन: यह एक अच्छा सवाल है, लेकिन उस मामले में मैं एक शून्य फ़ंक्शन (जैसा कि उल्लेख किया गया है) की तलाश करूँगा। इसके अलावा सिद्धांत में आप उनमें से किसी को भी चुन सकते हैं, क्योंकि वे सभी एक ही कार्य करेंगे, बस एक अलग प्रारूप में डेटा वापस करेंगे।
जोश के

2

Grrr .. अभी तक टिप्पणी करने के लिए पर्याप्त विशेषाधिकार नहीं ..

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

f a b  // application is left assoc: (f a) b

बी के प्रकार का उपयोग अधिभार संकल्प के लिए किया जा सकता है। कुछ परिस्थितियों में वापसी प्रकार पर भी C ++ अधिभार:

int (*f)(int) = g; // choses g based on type, not just signature

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


2

फंक्शन ओवरलोडिंग को लागू करने के खिलाफ केस-केस: 25 तरह के नाम-तरीके जो एक ही तरह के काम करते हैं, लेकिन कई तरह के पैटर्न में तर्कों के पूरी तरह से अलग सेट के साथ।

फ़ंक्शन-ओवरलोडिंग को लागू नहीं करने के खिलाफ उपयोग-मामला: ठीक उसी पैटर्न में प्रकारों के समान सेट के साथ 5 समान-नामित तरीके।

दिन के अंत में, मैं किसी भी मामले में उत्पादित एपीआई के लिए डॉक्स पढ़ने के लिए उत्सुक नहीं हूं।

लेकिन एक मामले में यह उपयोगकर्ताओं के बारे में क्या कर सकता है। दूसरे मामले में यह है कि भाषा प्रतिबंध के कारण उपयोगकर्ताओं को क्या करना चाहिए। IMO, यह बेहतर है कि कम से कम कार्यक्रम लेखकों की संभावना के लिए अनुमति दें ताकि वे अस्पष्टता बनाए बिना समझदारी से अधिभार के लिए पर्याप्त स्मार्ट हो सकें। जब आप उनके हाथों को थप्पड़ मारते हैं और विकल्प को दूर ले जाते हैं तो आप मूल रूप से अस्पष्टता की गारंटी देते हैं ऐसा होने जा रहा है। मुझे लगता है कि वे हमेशा गलत काम करेंगे मानने की तुलना में सही काम करने के लिए उपयोगकर्ता पर भरोसा करने के बारे में अधिक हूं। मेरे अनुभव में, संरक्षणवाद भाषा के समुदाय की ओर से और भी बुरे व्यवहार को जन्म देता है।


1

मैंने अपनी भाषा फेलिक्स में साधारण ओवरलोडिंग और मल्टी-टाइप टाइप-क्लास प्रदान करने का विकल्प चुना।

मुझे लगता है कि (ओपन) ओवरलोडिंग आवश्यक है, विशेष रूप से एक भाषा में जो बहुत सारे संख्यात्मक प्रकारों के रूप में है (फेलिक्स में सभी सी के संख्यात्मक प्रकार हैं)। हालाँकि C ++ के विपरीत, जो टेम्प्लेट बनाकर ओवरलोडिंग का दुरुपयोग करता है, इस पर निर्भर करता है, फेलिक्स पॉलीमॉर्फिज़्म पैरामीट्रिक है: आपको C ++ में टेम्प्लेट के लिए ओवरलोडिंग की आवश्यकता है क्योंकि C ++ में टेम्प्लेट बुरी तरह से डिज़ाइन किए गए हैं।

फेलिक्स में भी टाइप कक्षाएं दी जाती हैं। उन लोगों के लिए जो सी ++ जानते हैं, लेकिन हास्केल को ग्रो नहीं करते हैं, उन लोगों को अनदेखा करें जो इसे ओवरलोडिंग के रूप में वर्णित करते हैं। यह ओवरलोडिंग की तरह दूरस्थ रूप से नहीं है, बल्कि, यह टेम्पलेट विशेषज्ञता की तरह है: आप एक टेम्पलेट की घोषणा करते हैं जिसे आप लागू नहीं करते हैं, फिर विशेष मामलों के लिए कार्यान्वयन प्रदान करें जैसे कि आपको उनकी आवश्यकता है। टाइपिंग पैराओर्मिक रूप से बहुरूपी है, कार्यान्वयन तदर्थ तात्कालिकता द्वारा है, लेकिन यह अप्रतिबंधित होने का इरादा नहीं है: इसे इच्छित शब्दार्थ को लागू करना है।

हास्केल (और C ++) में आप शब्दार्थ नहीं बता सकते। C ++ में "कॉन्सेप्ट्स" विचार मोटे तौर पर शब्दार्थ को अनुमानित करने का एक प्रयास है। फेलिक्स में, आप स्वयंसिद्ध, कटौती, नींबू और प्रमेय के साथ इरादे का अनुमान लगा सकते हैं।

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

ओवरलोडिंग का प्राथमिक नुकसान इसे लागू करने के लिए आवश्यक जटिल एल्गोरिदम है। यह टाइप इंफ़ेक्शन के साथ बहुत अच्छी तरह से नहीं बैठता है: हालांकि दो पूरी तरह से अनन्य नहीं हैं, दोनों को करने के लिए एल्गोरिथ्म पर्याप्त जटिल है जो प्रोग्रामर शायद परिणामों की भविष्यवाणी करने में सक्षम नहीं होगा।

C ++ में यह एक समस्या भी है क्योंकि इसमें एक मैला मिलान एल्गोरिथ्म है और यह स्वचालित प्रकार के रूपांतरणों का भी समर्थन करता है: फेलिक्स I में इस समस्या का सटीक मिलान और स्वचालित प्रकार के रूपांतरणों की आवश्यकता नहीं है।

इसलिए आपके पास एक विकल्प है जो मुझे लगता है: ओवरलोडिंग या प्रकार का अनुमान। इंजेक्शन प्यारा है, लेकिन यह इस तरह से लागू करने के लिए बहुत कठिन है जो संघर्षों का सही ढंग से निदान करता है। उदाहरण के लिए, Ocaml आपको बताता है कि यह एक संघर्ष का पता लगाता है, लेकिन ऐसा नहीं है जहाँ यह अपेक्षित प्रकार से अनुमान नहीं लगाता है।

ओवरलोडिंग बहुत बेहतर नहीं है, भले ही आपके पास एक गुणवत्ता संकलक हो जो आपको सभी उम्मीदवारों को बताने की कोशिश करता है, यह पढ़ना मुश्किल हो सकता है कि क्या उम्मीदवार पॉलीमॉर्फिक हैं, और इससे भी बदतर अगर यह सी ++ टेम्पलेट हैकरी है।


दिलचस्प लगता है। मुझे और पढ़ना अच्छा लगेगा, लेकिन फेलिक्स वेब पेज पर डॉक्स का लिंक टूटा हुआ है।
स्वयं पर ध्यान दें -

हां, वर्तमान में पूरी साइट निर्माणाधीन है (फिर से), क्षमा करें।
22

0

संदर्भ के लिए नीचे आता है, लेकिन मुझे लगता है कि जब मैं किसी और द्वारा लिखित एक का उपयोग कर रहा हूं तो ओवरलोडिंग एक वर्ग को बहुत अधिक उपयोगी बनाता है। आप अक्सर कम अतिरेक के साथ समाप्त होते हैं।


0

अगर आप सी-फैमिली लैंग्वेज के साथ यूजर्स को पहचानना चाहते हैं तो आपको हां करना चाहिए क्योंकि आपके यूजर्स को यह उम्मीद होगी।

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