2015-09-17 17 views
20

में बेनामी/इनलाइन इंटरफ़ेस कार्यान्वयन मैंने अभी टाइपस्क्रिप्ट के साथ शुरुआत की है और मैं समझने की कोशिश कर रहा हूं कि निम्न इनलाइन ऑब्जेक्ट परिभाषा को वैध क्यों नहीं माना जाता है। मेरे पास ऑब्जेक्ट्स का संग्रह है - उनका प्रकार अप्रासंगिक है (मेरे लिए), लेकिन वे इंटरफ़ेस को कार्यान्वित करते हैं ताकि जब मैं उनके माध्यम से पुनरावृत्ति करूं तो मुझे पता है कि संग्रह में प्रत्येक ऑब्जेक्ट में इंटरफ़ेस विधियां मौजूद होंगी।टाइपस्क्रिप्ट

interface Doable { 
    do(); 
} 

function doThatThing (doableThing: Doable) { 
    doableThing.do(); 
} 

doThatThing({ 
    private message: 'ahoy-hoy!', // compiler error here 
    do:() => { 
     alert(this.message); 
    } 
}); 

संकलक त्रुटि संदेश है "प्रकार '{ message: string, do:() => void; }' के तर्क को आबंटित नहीं है:

मैं जब मैं निजी जानकारी की आवश्यकता विधि को लागू करने के लिए आवश्यक के साथ एक वस्तु बनाने की कोशिश की एक" संकलक "त्रुटि में आए करने योग्य टाइप करने के लिए। ऑब्जेक्ट शाब्दिक को ज्ञात गुण निर्दिष्ट करना होगा, और 'संदेश' टाइप करने योग्य प्रकार में मौजूद नहीं है "। ध्यान दें कि यदि मैं समारोह कॉल के बाहर वस्तु को परिभाषित एक ही संदेश दिया है यानि

var thing: Doable; 
thing = { 
    private message: 'ahoy-hoy!', // error here 
    do:() => { 
     alert(this.message); 
    } 
}; 
doThatThing(thing); 

अगर मैं "अप्रत्याशित" तरीकों के रूप में जोड़ एक ही त्रुटि तब होती है:

doThatThing({ 
    do:() => { 
     alert("ahoy hoy"); 
    }, 
    doSecretly:() => { // compiler error here now 
     alert("hi there"); 
    } 
}); 

मैं को देखा जावास्क्रिप्ट और पाया कि this इनलाइन वस्तु परिभाषा के दायरे में वैश्विक वस्तु के दायरे वाला जा रहा था:

var _this = this; // wait, no, why!? 
function doThatThing(doableThing) { 
    doableThing.do(); 
} 
doThatThing({ 
    message: 'ahoy-hoy!', 
    do: function() { 
     alert(_this.message); // uses global 
    } 
}); 

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

मैं पुष्टि कर सकता है कि "तय" संकलित जे एस अपेक्षित तरीके से काम:

function doThatThing(doableThing) { 
    doableThing.do(); 
} 

doThatThing({ 
    message: 'ahoy-hoy!', 
    do: function() { 
     alert(this.message); 
    } 
}); 

... और कहा कि, मेरे लिए समझ में आता है (जहाँ तक मैं समझता हूँ) इस परोक्ष वस्तु निर्माता बुला रहा है क्योंकि , इसलिए this को नए ऑब्जेक्ट इंस्टेंस में स्कॉप्ड किया जाना चाहिए।

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

क्षमा करें, यह लंबे समय तक निकला की तुलना में मैं इरादा ... सारांश में, मैं पूछ रहा हूँ:

  1. क्यों कि इनलाइन इंटरफेस कार्यान्वयन ("गुमनाम वर्ग", के रूप में in Java कहा जाएगा) मान्य नहीं होता टाइपस्क्रिप्ट में? विशेष रूप से, उस कंपाइलर त्रुटि का क्या अर्थ है, और यह किसके खिलाफ सुरक्षा करता है?
  2. "संकलित" जावास्क्रिप्ट में उत्पन्न वैश्विक वस्तु का दायरा-पुन: असाइनमेंट क्यों है?
  3. मान लीजिए कि यह मेरी त्रुटि है (उदाहरण के लिए कि कुछ अवांछनीय स्थिति के खिलाफ सुरक्षा के लिए संकलक त्रुटि आवश्यक है), वास्तव में एक वर्ग को स्पष्ट रूप से स्पष्ट रूप से घोषित करने का एकमात्र समाधान है, जैसे?
interface Doable { 
    do() : void; 
} 

class DoableThingA implements Doable { // would prefer to avoid this ... 
    private message: string = 'ahoy-hoy'; 
    do() { 
     alert(this.message); 
    } 
} 

class DoableThingB implements Doable { // ... as well as this, since there will be only one instance of each 
    do() { 
     document.getElementById("example").innerHTML = 'whatever'; 
    } 
} 

function doThatThing (doableThing: Doable) { 
    doableThing.do(); 
} 

var things: Array<Doable>; 
things = new Array<Doable>(); 
things.push(new DoableThingA()); 
things.push(new DoableThingB()); 

for (var i = 0; i < things.length; i++) { 
    doThatThing(things[i]); 
} 

पी.एस. संकलक त्रुटि केवल तब दिखाई दी जब मैंने आज टीएस 1.6 में अपग्रेड किया, हालांकि संकलित जेएस में दोषपूर्ण गुंजाइश बग 1.6 और 1.5 दोनों में होता है।

अद्यतन: फ़्राँस्वा Cardinaux this answer के लिए एक लिंक है, जो एक प्रकार अभिकथन उपयोग करने की सलाह प्रदान की है, लेकिन यह केवल अनुचित गुंजाइश की वजह से एक तर्क त्रुटि संकलक त्रुटि दूर करता है और वास्तव में कारण बनता है:

interface Doable { 
    do(); 
} 

function doThatThing (doableThing: Doable) { 
    doableThing.do(); 
} 

doThatThing(<Doable>{ // assert that this object is a Doable 
    private message: 'ahoy-hoy!', // no more compiler error here 
    do:() => { 
     alert(this.message); 
    } 
}); 

संकलित जेएस को देखते हुए, यह गलत है:

var _this = this; // very wrong, and now hidden 
function doThatThing(doableThing) { 
    doableThing.do(); 
} 
doThatThing({ 
    message: 'ahoy-hoy!', 
    do: function() { 
     alert(_this.message); // s/b "this.message", which works in JS (try it) 
    } 
}); 

उत्तर

13

ठीक है, अंततः मुझे प्रश्न 2 की समस्या की खोज हुई - मैं वसा का उपयोग कर रहा था

doThatThing(<Doable>{ 
    private message: 'ahoy-hoy!', 
    do:() => { // using fat arrow: global scope replaces new object's scope 
     alert(this.message); 
    } 
}); 

... कौन सी विधि में वैश्विक क्षेत्र "चूसा": rrow => यहाँ वस्तु की प्रणाली की घोषणा करने के लिए। समस्या अब सिंटैक्स का उपयोग कर रहा है फिक्स्ड, तो जैसे:

सारांश में
doThatThing(<Doable>{ 
    private message: 'ahoy-hoy!', 
    do: function() { // using "regular" anonymous function syntax, "this" meaning is preserved 
     alert(this.message); 
    } 
}); 

तो:

  1. अनुत्तरित;
  2. मेरे कोड में एक टाइपो था, और मुझे "=>" के बजाय "function()" का उपयोग करना चाहिए था; और,
  3. इंटरफ़ेस के साथ ऑब्जेक्ट को टाइप करने से कंपाइलर त्रुटि को हटा दिया जाता है।
+1

भावी पाठकों के लिए एक sidenote के रूप में: इनलाइन फ़ंक्शंस को 'फ़ंक्शन' कीवर्ड के बिना भी परिभाषित किया जा सकता है: '{message: 'ahoy-hoy!', Do() {alert (this.message); }} '। यह वाक्यविन्यास एक सामान्य कार्य के लिए सिर्फ एक शॉर्टेंड है और यह एक अक्षीय 'यह' तीर कार्यों की तरह बाध्य नहीं करता है। –

+0

का उपयोग किया जाना चाहिए 'do =() => {...}' इसके बजाय - असाइनमेंट सुनिश्चित करता है कि यह 'इवेंट हैंडलर इत्यादि से बुलाए जाने पर भी' करने योग्य 'इंस्टेंस स्कोप का उपयोग कर रहा है। – Rycochet