टाइपस्क्रिप्ट फ़ंक्शन ओवरलोडिंग है


243

टाइपस्क्रिप्ट भाषा की धारा 6.3 फ़ंक्शन ओवरलोडिंग के बारे में बात करती है और इसे लागू करने के तरीके पर ठोस उदाहरण देती है। हालाँकि अगर मैं ऐसा कुछ करने की कोशिश करता हूँ:

export class LayerFactory { 

    constructor (public styleFactory: Symbology.StyleFactory) { }

    createFeatureLayer (userContext : Model.UserContext, mapWrapperObj : MapWrapperBase) : any {           
         throw "not implemented";
    }                 

    createFeatureLayer(layerName : string, style : any) : any {
        throw "not implemented";
     }        

}

मुझे एक कंपाइलर त्रुटि मिलती है जो डुप्लिकेट पहचानकर्ता को इंगित करती है भले ही फ़ंक्शन पैरामीटर विभिन्न प्रकार के हों। यहां तक ​​कि अगर मैं दूसरे createFeatureLayer फ़ंक्शन में एक अतिरिक्त पैरामीटर जोड़ता हूं, तो भी मुझे एक कंपाइलर त्रुटि मिलती है। विचार, कृपया।


जवाबों:


189

ऐसा इसलिए हो सकता है, क्योंकि जब दोनों फ़ंक्शन जावास्क्रिप्ट में संकलित किए जाते हैं, तो उनके हस्ताक्षर पूरी तरह से समान होते हैं। चूंकि जावास्क्रिप्ट में प्रकार नहीं हैं, इसलिए हम समान संख्या में तर्क लेते हुए दो कार्य बनाते हैं। इसलिए, टाइपस्क्रिप्ट हमें ऐसे कार्यों को बनाने से प्रतिबंधित करता है।

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

असल में, हम जो कर रहे हैं, हम सिर्फ एक फ़ंक्शन और कई घोषणाएँ बना रहे हैं ताकि टाइपस्क्रिप्ट संकलन त्रुटियों को न दें। जब यह कोड जावास्क्रिप्ट में संकलित किया जाता है, तो अकेले ठोस कार्य दिखाई देगा। एक जावास्क्रिप्ट फ़ंक्शन के रूप में कई तर्कों को पारित करके बुलाया जा सकता है, यह सिर्फ काम करता है।


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

8
आप इसे ऐसे कहते हैं जैसे टाइपस्क्रिप्ट में ओवरलोडिंग केवल मापदंडों की संख्या के आधार पर संभव है, जबकि प्रकार के आधार पर ओवरलोडिंग भी संभव है जैसा कि स्टीव फेंटन के उत्तर में दिखाया गया है।
Matthijs वेसल्स

9
यह एक प्रकार से लंगड़ा है; टाइपस्क्रिप्ट को वास्तव में "मेटा फंक्शन" उत्पन्न करना चाहिए जो विशिष्ट रूप से नामित कार्यान्वयन को चुनता है जो कि इसे पारित किया गया था। अब यह कैसे हो सकता है एक दरार है जहाँ आप संकलक को पास कर सकते हैं लेकिन आपके प्रकार के सूँघने का कार्यान्वयन गलत हो सकता है।
यहेजकेल विक्टर

5
@EzekielVictor टाइपस्क्रिप्ट रन टाइम में जाँच के प्रकार का एक विश्वसनीय तरीका था, तो यह करना होगा।
कंटक 23

3
यह और भी जटिल है, यह जावास्क्रिप्ट के प्रकारों के साथ उल्लेखनीय है, लेकिन टीएस-विशिष्ट धारणाएं जैसे इंटरफेस, typeएस, एनम, जेनरिक, आदि रनटाइम में खो जाते हैं। इसलिए भी आप ऐसा नहीं कर सकते someObject instanceof ISomeInterfaceDefinedInTypeScript
मॉर्गन टोवरे क्विंग

209

जब आप टाइपस्क्रिप्ट में ओवरलोड करते हैं, तो आपके पास कई हस्ताक्षर के साथ केवल एक कार्यान्वयन होता है।

class Foo {
    myMethod(a: string);
    myMethod(a: number);
    myMethod(a: number, b: string);
    myMethod(a: any, b?: string) {
        alert(a.toString());
    }
}

केवल तीन ओवरलोड को एक विधि कॉल के लिए संभावित हस्ताक्षर के रूप में टाइपस्क्रिप्ट द्वारा पहचाना जाता है, वास्तविक कार्यान्वयन नहीं।

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

टाइपस्क्रिप्ट 1.4

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

myMethod(a: string | number, b?: string) {
    alert(a.toString());
}

के प्रकार aहै "या तो stringया number"।


बहुत बढ़िया जवाब। मैं यह बताना चाहता हूं कि, यह तब मददगार नहीं हो सकता है जब कोई ऐसे कारणों से अधिक भार उठाने की कोशिश कर रहा हो जैसे: मैं एक उदाहरण देना चाहूंगा, जहां एक ही निर्माता का उपयोग करके, मैं सभी अपेक्षित गुणों को परिभाषित करने वाली एक वस्तु को पारित कर सकता हूं और में एक उदाहरण, अलग-अलग दृष्टांतों को पास करें: class Foo { constructor(obj) { } constructor (a: number, b: string, c: boolean) {} }
Hlawuleka MAS

सामान्य तौर पर, मैं नहीं बल्कि एक कारखाने विधि मुझे हर तरह एक वस्तु बनाने के लिए उपयोग करना चाहते हैं - शाखा करने की कोई जरूरत है, तो आप कॉल नहीं है Foo.fromObject(obj)और Foo.fromJson(str)और इतने पर।
फेंटन

लेकिन यह बताता है कि कोई भी हमेशा एक पैरामीटर या एक स्ट्रिंग के रूप में अपने मापदंडों को पारित करेगा, क्या होगा अगर मैं उन्हें अलग से पारित करना चाहता हूं, जैसा कि मेरी पिछली टिप्पणी से उजागर किया गया है? Foo.methos(1, 2, 3) Foo.method(1) Foo.method(Obj) मैंने यह भी देखा कि आपके पास Fooकक्षा में अलग-अलग तरीके हैं , fromObject और fromJson?
हलावुल्का मास

1
यदि आप स्रोत में उस अंतर का पालन करते हैं, तो आप आमतौर पर पाएंगे कि इसकी कोई आवश्यकता नहीं है। उदाहरण के लिए, आपको टाइप करना है myNumया myObjवैसे भी, तो क्यों न अलग-अलग तरीके हों और सब कुछ स्पष्ट कर दिया जाए / अनावश्यक ब्रांचिंग तर्क से बचें।
फेंटन

2
ध्यान दें कि यदि आप मापदंडों के आधार पर अलग-अलग रिटर्न प्रकार चाहते हैं तो संघ प्रकार का उपयोग करना समस्याग्रस्त हो सकता है। जेनरिक के साथ हल किया जा सकता है यदि रिटर्न प्रकार हमेशा पैरामीटर प्रकारों में से एक से मेल खाता है, लेकिन अन्य मामलों के लिए ओवरलोड सबसे अच्छा समाधान है।
जॉन मोंटगोमरी

45

आप फ़ंक्शन को एक प्रकार का ओवरलोडेड फ़ंक्शन घोषित कर सकते हैं जिसमें एक प्रकार है जिसमें कई आह्वान हस्ताक्षर हैं:

interface IFoo
{
    bar: {
        (s: string): number;
        (n: number): string;
    }
}

फिर निम्नलिखित:

var foo1: IFoo = ...;

var n: number = foo1.bar('baz');     // OK
var s: string = foo1.bar(123);       // OK
var a: number[] = foo1.bar([1,2,3]); // ERROR

फ़ंक्शन की वास्तविक परिभाषा एकवचन होनी चाहिए और इसके तर्कों पर आंतरिक रूप से उचित प्रेषण करना चाहिए।

उदाहरण के लिए, एक वर्ग का उपयोग करना (जो लागू हो सकता है IFoo, लेकिन उसके पास नहीं है):

class Foo
{
    public bar(s: string): number;
    public bar(n: number): string;
    public bar(arg: any): any 
    {
        if (typeof(arg) === 'number')
            return arg.toString();
        if (typeof(arg) === 'string')
            return arg.length;
    }
}

यहां दिलचस्प बात यह है कि anyफॉर्म अधिक विशेष रूप से टाइप किए गए ओवरराइड्स द्वारा छिपा हुआ है।

var foo2: new Foo();

var n: number = foo2.bar('baz');     // OK
var s: string = foo2.bar(123);       // OK
var a: number[] = foo2.bar([1,2,3]); // ERROR

1

सामान्य रूप से कार्य अधिभार क्या है?

फंक्शन ओवरलोडिंग या मेथड ओवरलोडिंग एक ही नाम के कई कार्यों को अलग-अलग कार्यान्वयन ( विकिपीडिया ) के साथ बनाने की क्षमता है


जेएस में फ़ंक्शन ओवरलोडिंग क्या है?

जेएस में यह सुविधा संभव नहीं है - अंतिम परिभाषित कार्य कई घोषणाओं के मामले में लिया जाता है:

function foo(a1, a2) { return `${a1}, ${a2}` }
function foo(a1) { return `${a1}` } // replaces above `foo` declaration
foo(42, "foo") // "42"

... और टीएस में?

ओवरलोड , जेएस रनटाइम पर कोई प्रभाव नहीं के साथ एक संकलन समय निर्माण कर रहे हैं :

function foo(s: string): string // overload #1 of foo
function foo(s: string, n: number): number // overload #2 of foo
function foo(s: string, n?: number): string | number {/* ... */} // foo implementation

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


टीएस में विधि अधिभार: एक अधिक जटिल उदाहरण

अतिभारित कार्य करने के लिए एक समान तरीके से ओवरलोड क्लास विधि का उपयोग किया जा सकता है:

class LayerFactory {
    createFeatureLayer(a1: string, a2: number): string
    createFeatureLayer(a1: number, a2: boolean, a3: string): number
    createFeatureLayer(a1: string | number, a2: number | boolean, a3?: string)
        : number | string { /*... your implementation*/ }
}

const fact = new LayerFactory()
fact.createFeatureLayer("foo", 42) // string
fact.createFeatureLayer(3, true, "bar") // number

कंपाइलर द्वारा लागू किए गए फंक्शन कार्यान्वयन सभी ओवरलोड हस्ताक्षर के अनुकूल होने के कारण, अलग-अलग ओवरलोड संभव हैं।

अधिक जानकारी:


0

दूसरों के लिए एक सिर के रूप में, मैंने माना है कि वेबरैक द्वारा टाइप 2 द्वारा संकलित टाइपस्क्रिप्ट द्वारा कम से कम प्रकट होता है, आप चुपचाप ओवरलो विधि के बजाय ओवरवेटन प्राप्त करते हैं।

myComponent {
  method(): { console.info("no args"); },
  method(arg): { console.info("with arg"); }
}

कॉलिंग:

myComponent.method()

तर्क के साथ विधि को निष्पादित करने के लिए लगता है, चुपचाप उत्पादन के साथ नो-arg संस्करण की अनदेखी कर रहा है:

with arg

2
आप अपने अधिभार के लिए अलग-अलग निकायों की घोषणा नहीं कर सकते, केवल अलग-अलग हस्ताक्षर।
एड्रिस

5
मुझे यकीन नहीं है कि आप किस प्रकार के टाइपस्क्रिप्ट कंपाइलर का उपयोग कर रहे हैं, लेकिन वर्तमान संस्करण Duplicate function implementationइस तरह कोड के लिए चेतावनी देता है।
Royston Shufflebotham

0

टाइपस्क्रिप्ट में ओवरलोडिंग

विकिपीडिया, (और कई प्रोग्रामिंग पुस्तकों के अनुसार) विधि / कार्य अतिभार की परिभाषा निम्नलिखित है:

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

टाइपस्क्रिप्ट में हम एक ही फ़ंक्शन के अलग-अलग कार्यान्वयन नहीं कर सकते हैं जिन्हें संख्या और प्रकार के तर्कों के अनुसार कहा जाता है। इसका कारण यह है कि जब TS को JS में संकलित किया जाता है, JS के कार्यों में निम्नलिखित विशेषताएं होती हैं:

  • जावास्क्रिप्ट फ़ंक्शन परिभाषाएँ अपने मापदंडों के लिए डेटा प्रकार निर्दिष्ट नहीं करती हैं
  • जावास्क्रिप्ट फ़ंक्शन जब बुलाया जाता है तो तर्कों की संख्या की जांच नहीं करते हैं

इसलिए, एक सख्त अर्थ में, कोई तर्क दे सकता है कि टीएस फ़ंक्शन ओवरलोडिंग मौजूद नहीं है। हालांकि, ऐसी चीजें हैं जो आप अपने टीएस कोड के भीतर कर सकते हैं जो पूरी तरह से फ़ंक्शन ओवरलोडिंग की नकल कर सकते हैं।

यहाँ एक उदाहरण है:

function add(a: number, b: number, c: number): number;
function add(a: number, b: number): any;
function add(a: string, b: string): any;

function add(a: any, b: any, c?: any): any {
  if (c) {
    return a + c;
  }
  if (typeof a === 'string') {
    return `a is ${a}, b is ${b}`;
  } else {
    return a + b;
  }
}

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

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