मैं जावास्क्रिप्ट के साथ OOP बनाना सीख रहा हूँ । क्या इसकी इंटरफ़ेस अवधारणा (जैसे जावा की interface
) है?
तो मैं एक श्रोता बनाने में सक्षम हो जाएगा ...
मैं जावास्क्रिप्ट के साथ OOP बनाना सीख रहा हूँ । क्या इसकी इंटरफ़ेस अवधारणा (जैसे जावा की interface
) है?
तो मैं एक श्रोता बनाने में सक्षम हो जाएगा ...
जवाबों:
"इस वर्ग के पास ये कार्य होने चाहिए" की कोई धारणा नहीं है (अर्थात, प्रति क्रमांक नहीं), क्योंकि:
इसके बजाय, जावास्क्रिप्ट का उपयोग करता है जिसे बतख टाइपिंग कहा जाता है । (यदि यह एक बतख की तरह चलता है, और एक बतख की तरह चुटकी लेता है, जहाँ तक JS की परवाह है, तो यह एक बतख है।) यदि आपकी वस्तु में नीम हकीम (), चलना (), और मक्खी () की विधियाँ हैं, तो कोड जहाँ भी इसका उपयोग हो सकता है। एक ऐसी वस्तु जो कुछ "डकरेबल" इंटरफेस के कार्यान्वयन की आवश्यकता के बिना चल सकती है, बच सकती है और उड़ सकती है। इंटरफ़ेस वास्तव में उन फ़ंक्शन का सेट है जो कोड का उपयोग करता है (और उन फ़ंक्शन से रिटर्न मान), और बतख टाइपिंग के साथ, आपको यह मुफ़्त मिलता है।
अब, यदि आपका फोन कॉल करने की कोशिश नहीं करता है, तो आपका कोड आधे से भी कम नहीं होगा some_dog.quack()
; आपको एक टाइपर्रर मिलेगा। सच कहूं, अगर आप कुत्तों को शांत करने के लिए कह रहे हैं, तो आपको थोड़ी बड़ी समस्याएं हैं; जब आप अपने सभी बत्तख को एक पंक्ति में रखते हैं, तो बोलने के लिए बतख टाइपिंग सबसे अच्छा काम करती है, और जब तक आप उन्हें सामान्य जानवरों के रूप में नहीं मान रहे हैं, तब तक कुत्तों और बत्तखों को एक साथ नहीं होने दें। दूसरे शब्दों में, भले ही इंटरफ़ेस तरल है, यह अभी भी है; यह अक्सर एक कुत्ते को पास करने के लिए एक त्रुटि है जो इसे पहले स्थान पर छोड़ने और उड़ने की उम्मीद करता है।
लेकिन अगर आपको यकीन है कि आप सही काम कर रहे हैं, तो आप इसे इस्तेमाल करने की कोशिश करने से पहले किसी विशेष विधि के अस्तित्व के लिए परीक्षण करके क्वैकिंग-डॉग समस्या के आसपास काम कर सकते हैं। कुछ इस तरह
if (typeof(someObject.quack) == "function")
{
// This thing can quack
}
इसलिए आप उन सभी तरीकों की जांच कर सकते हैं जिनका उपयोग करने से पहले आप उनका उपयोग कर सकते हैं। सिंटैक्स एक प्रकार का बदसूरत है, हालांकि। थोड़ा प्रीतिकर तरीका है:
Object.prototype.can = function(methodName)
{
return ((typeof this[methodName]) == "function");
};
if (someObject.can("quack"))
{
someObject.quack();
}
यह मानक जावास्क्रिप्ट है, इसलिए इसका उपयोग करने लायक किसी भी जेएस दुभाषिया में काम करना चाहिए। इसमें अंग्रेजी की तरह पढ़ने का अतिरिक्त लाभ है।
आधुनिक ब्राउज़रों के लिए (अर्थात, IE 6-8 के अलावा कोई भी ब्राउज़र), संपत्ति को दिखाने से रखने का एक तरीका भी है for...in
:
Object.defineProperty(Object.prototype, 'can', {
enumerable: false,
value: function(method) {
return (typeof this[method] === 'function');
}
}
समस्या यह है कि IE7 ऑब्जेक्ट्स के पास बिल्कुल नहीं है .defineProperty
, और IE8 में, यह कथित तौर पर केवल होस्ट ऑब्जेक्ट्स (यानी, DOM एलिमेंट्स और ऐसे) पर काम करता है। यदि संगतता एक समस्या है, तो आप उपयोग नहीं कर सकते .defineProperty
। (मैं IE6 का उल्लेख भी नहीं करूंगा, क्योंकि यह चीन के बाहर अब अप्रासंगिक है।)
एक और मुद्दा यह है कि कुछ कोडिंग शैली यह मान लेना पसंद करती हैं कि हर कोई खराब कोड लिखता है, और Object.prototype
यदि कोई आँख बंद करके उपयोग करना चाहता है तो उसे संशोधित करना प्रतिबंधित है for...in
। यदि आप इस बारे में परवाह करते हैं, या (IMO टूटा हुआ ) कोड का उपयोग कर रहे हैं , तो थोड़ा अलग संस्करण आज़माएँ:
function can(obj, methodName)
{
return ((typeof obj[methodName]) == "function");
}
if (can(someObject, "quack"))
{
someObject.quack();
}
for...in
है - और हमेशा ऐसे खतरों से भरा हुआ है, और जो कोई भी ऐसा करता है, वह कम से कम यह विचार किए बिना करता है कि किसी ने जोड़ा Object.prototype
(एक असामान्य तकनीक नहीं है, उस लेख के स्वयं के प्रवेश द्वारा) किसी और के हाथों में अपने कोड को तोड़ देगा।
for...in
समस्या से बच सकते हैं । developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
for...in
समस्या" अभी भी कुछ हद तक मौजूद होगी, क्योंकि वहाँ हमेशा मैला कोड होगा ... ठीक है, वह, और Object.defineProperty(obj, 'a', {writable: true, enumerable: false, value: 3});
बस की तुलना में थोड़ा अधिक काम है obj.a = 3;
। मैं पूरी तरह से समझ सकता हूं कि लोग इसे अधिक बार करने की कोशिश नहीं कर रहे हैं। : P
डस्टिन डियाज़ द्वारा ' जावास्क्रिप्ट डिज़ाइन पैटर्न ' की एक प्रति उठाओ । डक टाइपिंग के माध्यम से जावास्क्रिप्ट इंटरफेस को लागू करने के लिए समर्पित कुछ अध्याय हैं। यह एक अच्छा पढ़ने के रूप में अच्छी तरह से है। लेकिन नहीं, इंटरफ़ेस का कोई भाषा मूल कार्यान्वयन नहीं है, आपको डक टाइप करना होगा ।
// example duck typing method
var hasMethods = function(obj /*, method list as strings */){
var i = 1, methodName;
while((methodName = arguments[i++])){
if(typeof obj[methodName] != 'function') {
return false;
}
}
return true;
}
// in your code
if(hasMethods(obj, 'quak', 'flapWings','waggle')) {
// IT'S A DUCK, do your duck thang
}
जावास्क्रिप्ट (ECMAScript संस्करण 3) में भविष्य के उपयोग के लिएimplements
आरक्षित शब्द है । मुझे लगता है कि यह वास्तव में इस उद्देश्य के लिए है, हालांकि, विनिर्देश को प्राप्त करने के लिए एक भीड़ में, उनके पास यह निर्धारित करने के लिए समय नहीं था कि इसके साथ क्या करना है, इसलिए, वर्तमान समय में, ब्राउज़र इसके अलावा कुछ भी नहीं करते हैं यदि आप इसे किसी चीज़ के लिए उपयोग करने का प्रयास करते हैं, तो इसे वहां बैठें और कभी-कभी शिकायत करें।
यह संभव है और Object.implement(Interface)
तर्क के साथ अपनी खुद की विधि बनाने के लिए वास्तव में काफी आसान है, जब भी किसी विशेष वस्तु में गुणों / कार्यों का एक विशेष सेट लागू नहीं होता है।
मैंने ऑब्जेक्ट-ओरिएंटेशन पर एक लेख लिखा है, जहां निम्नानुसार मेरे अपने अंकन का उपयोग करें :
// Create a 'Dog' class that inherits from 'Animal'
// and implements the 'Mammal' interface
var Dog = Object.extend(Animal, {
constructor: function(name) {
Dog.superClass.call(this, name);
},
bark: function() {
alert('woof');
}
}).implement(Mammal);
इस विशेष बिल्ली को त्वचा करने के कई तरीके हैं, लेकिन यह वह तर्क है जिसका उपयोग मैंने अपने स्वयं के इंटरफ़ेस कार्यान्वयन के लिए किया था। मुझे लगता है कि मैं इस दृष्टिकोण को पसंद करता हूं, और इसे पढ़ना और उपयोग करना आसान है (जैसा कि आप ऊपर देख सकते हैं)। इसका मतलब है एक 'लागू' पद्धति को जोड़ना Function.prototype
जिससे कुछ लोगों को समस्या हो सकती है, लेकिन मुझे लगता है कि यह खूबसूरती से काम करता है।
Function.prototype.implement = function() {
// Loop through each interface passed in and then check
// that its members are implemented in the context object (this).
for(var i = 0; i < arguments.length; i++) {
// .. Check member's logic ..
}
// Remember to return the class being tested
return this;
}
var interf = arguments[i]; for (prop in interf) { if (this.prototype[prop] === undefined) { throw 'Member [' + prop + '] missing from class definition.'; }}
। अधिक विस्तृत उदाहरण के लिए लेख लिंक के नीचे देखें ।
हालाँकि जावास्क्रिप्ट का प्रकार नहीं है interface
, अक्सर इसकी आवश्यकता होती है। जावास्क्रिप्ट के गतिशील प्रकृति और प्रोटोटाइप-इनहेरिटेंस के उपयोग से संबंधित कारणों के लिए, कक्षाओं में लगातार इंटरफेस सुनिश्चित करना मुश्किल है - हालांकि, ऐसा करना संभव है; और अक्सर अनुकरण किया।
इस बिंदु पर, जावास्क्रिप्ट में इंटरफेसेस का अनुकरण करने के लिए कुछ विशेष तरीके हैं; दृष्टिकोण पर भिन्नता आम तौर पर कुछ जरूरतों को संतुष्ट करती है, जबकि अन्य को अनसुना कर दिया जाता है। अक्सर बार, सबसे मजबूत दृष्टिकोण अत्यधिक बोझिल होता है और कार्यान्वयनकर्ता (डेवलपर) को स्तब्ध कर देता है।
यहाँ Interfaces / Abstract Classes के लिए एक दृष्टिकोण दिया गया है जो बहुत बोझिल नहीं है, खोजपूर्ण है, संक्षेप के अंदर कार्यान्वयन को कम से कम रखता है, और गतिशील या कस्टम कार्यप्रणाली के लिए पर्याप्त जगह छोड़ता है:
function resolvePrecept(interfaceName) {
var interfaceName = interfaceName;
return function curry(value) {
/* throw new Error(interfaceName + ' requires an implementation for ...'); */
console.warn('%s requires an implementation for ...', interfaceName);
return value;
};
}
var iAbstractClass = function AbstractClass() {
var defaultTo = resolvePrecept('iAbstractClass');
this.datum1 = this.datum1 || defaultTo(new Number());
this.datum2 = this.datum2 || defaultTo(new String());
this.method1 = this.method1 || defaultTo(new Function('return new Boolean();'));
this.method2 = this.method2 || defaultTo(new Function('return new Object();'));
};
var ConcreteImplementation = function ConcreteImplementation() {
this.datum1 = 1;
this.datum2 = 'str';
this.method1 = function method1() {
return true;
};
this.method2 = function method2() {
return {};
};
//Applies Interface (Implement iAbstractClass Interface)
iAbstractClass.apply(this); // .call / .apply after precept definitions
};
रिसॉल्वर को प्रिसेप्ट करें
resolvePrecept
समारोह अपने के अंदर उपयोग करने के लिए एक उपयोगिता और सहायक समारोह है सार क्लास । इसका काम एन्कैप्सुलेटेड प्रीसेज़ (डेटा और व्यवहार) के अनुकूलित कार्यान्वयन-हैंडलिंग के लिए अनुमति देना है । यह त्रुटियों को फेंक सकता है या चेतावनी दे सकता है - और - कार्यान्वयनकर्ता वर्ग के लिए एक डिफ़ॉल्ट मान असाइन करें।
iAbstractClass
iAbstractClass
इंटरफ़ेस प्रयोग की जाने वाली परिभाषित करता है। इसका दृष्टिकोण अपने कार्यान्वयनकर्ता वर्ग के साथ एक मौन समझौता करता है। यह इंटरफ़ेस प्रत्येक प्रीसेप्ट को एक ही सटीक प्रीसेप्ट नामस्थान - या - जो कुछ भी प्रेज़ॉल रिज़ॉल्वर फ़ंक्शन देता है, प्रदान करता है। हालांकि, टैसिट समझौता एक संदर्भ में लागू होता है - कार्यान्वयन का एक प्रावधान।
implementor
Implementor बस (एक अंतरफलक के साथ 'इस बात से सहमत' iAbstractClass इस मामले में) और के उपयोग के द्वारा यह लागू होता है निर्माता-अपहरण : iAbstractClass.apply(this)
। ऊपर दिए गए डेटा और व्यवहार को परिभाषित करके, और फिर इंटरफ़ेस के निर्माता को हाईजैक करना - इंटरफ़ेस निर्माता के लिए कार्यान्वयन के संदर्भ को पारित करना - हम यह सुनिश्चित कर सकते हैं कि कार्यान्वयन का ओवरराइड जोड़ा जाएगा, और वह इंटरफ़ेस चेतावनी और डिफ़ॉल्ट मानों की खोज करेगा।
यह एक बहुत ही गैर-बोझिल दृष्टिकोण है जिसने समय और विभिन्न परियोजनाओं के लिए मेरी टीम और मैंने बहुत अच्छी तरह से सेवा की है। हालाँकि, इसमें कुछ कैविटीज़ और कमियां हैं।
कमियां
यद्यपि यह आपके सॉफ़्टवेयर में एक महत्वपूर्ण डिग्री तक स्थिरता को लागू करने में मदद करता है, यह सही इंटरफेस को लागू नहीं करता है - लेकिन उनका अनुकरण करता है। हालाँकि परिभाषाएँ, चूक और चेतावनी या त्रुटियों का पता लगाया जाता है, उपयोग की खोज डेवलपर द्वारा लागू की जाती है और इसका मूल्यांकन किया जाता है (जैसा कि जावास्क्रिप्ट विकास के बहुत से)।
यह प्रतीत होता है "जावास्क्रिप्ट में इंटरफेस" के लिए सबसे अच्छा तरीका है , हालांकि, मैं निम्नलिखित हल देखना पसंद करूंगा:
delete
कार्यों से मुक्त करेंउस ने कहा, मुझे आशा है कि इससे आपको उतना ही मदद मिलेगी, जितना कि मेरी टीम और मैं।
आपको जावा में इंटरफेस की जरूरत है क्योंकि यह वैधानिक रूप से टाइप किया गया है और संकलन के दौरान कक्षाओं के बीच अनुबंध ज्ञात होना चाहिए। जावास्क्रिप्ट में यह अलग है। जावास्क्रिप्ट गतिशील रूप से टाइप किया गया है; इसका मतलब है कि जब आप वस्तु प्राप्त करते हैं तो आप जांच सकते हैं कि क्या यह एक विशिष्ट विधि है और इसे कॉल करें।
yourMethod
प्रविष्टि # 5 की Superclass
व्यवहार्यता में डाल सकता है , और प्रत्येक उपवर्ग के लिए जिसका अपना है yourMethod
, बस इंगित करता है कि उपवर्ग की प्रविष्टि 5 उचित कार्यान्वयन पर।
Implementation
वह SomeInterface
यह नहीं कहता है कि यह पूरे इंटरफ़ेस को लागू करता है। इसकी जानकारी है कि "मैं लागू करता हूं" कहता है SomeInterface.yourMethod
और इसके लिए विधि परिभाषा पर अंक देता है Implementation.yourMethod
। जब JVM कॉल करता है SomeInterface.yourMethod
, तो यह उस इंटरफ़ेस की विधि के कार्यान्वयन के बारे में जानकारी के लिए कक्षा में दिखता है, और पाता है कि इसे कॉल करने की आवश्यकता है Implementation.yourMethod
।
आशा है, कि जो कोई भी अभी भी उत्तर की तलाश में है वह इसे मददगार पाता है।
आप एक प्रॉक्सी का उपयोग करके देख सकते हैं (यह ECMAScript 2015 के बाद से मानक है): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
latLngLiteral = new Proxy({},{
set: function(obj, prop, val) {
//only these two properties can be set
if(['lng','lat'].indexOf(prop) == -1) {
throw new ReferenceError('Key must be "lat" or "lng"!');
}
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//latitude is in range between 0 and 90
if(prop == 'lat' && !(0 < val && val < 90)) {
throw new RangeError('Position is out of range!');
}
//longitude is in range between 0 and 180
else if(prop == 'lng' && !(0 < val && val < 180)) {
throw new RangeError('Position is out of range!');
}
obj[prop] = val;
return true;
}
});
तब आप आसानी से कह सकते हैं:
myMap = {}
myMap.position = latLngLiteral;
जब आप ट्रांसकम्पायर का उपयोग करना चाहते हैं, तब आप टाइपस्क्रिप्ट को आज़मा सकते हैं। यह प्रारूप ईसीएमए सुविधाओं का समर्थन करता है (प्रस्ताव में, इंटरफेस को " प्रोटोकॉल " कहा जाता है ) जो कि कॉफ़ीस्क्रिप्ट या बेबीलोन जैसी भाषाओं के समान है।
टाइपस्क्रिप्ट में आपका इंटरफ़ेस जैसा दिख सकता है:
interface IMyInterface {
id: number; // TypeScript types are lowercase
name: string;
callback: (key: string; value: any; array: string[]) => void;
type: "test" | "notATest"; // so called "union type"
}
आप क्या नहीं कर सकते:
जावास्क्रिप्ट में कोई देशी इंटरफेस नहीं है, इंटरफ़ेस को अनुकरण करने के कई तरीके हैं। मैंने एक पैकेज लिखा है जो यह करता है
आप यहाँ आरोपण देख सकते हैं
जावास्क्रिप्ट में इंटरफेस नहीं है। लेकिन इसे डक-टाइप किया जा सकता है, एक उदाहरण यहां पाया जा सकता है:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
मुझे पता है कि यह एक पुराना है, लेकिन मैंने हाल ही में खुद को इंटरफेस के खिलाफ वस्तुओं की जांच के लिए एक आसान एपीआई की आवश्यकता है। तो मैंने यह लिखा: https://github.com/tomhicks/methodical
यह एनपीएम के माध्यम से भी उपलब्ध है: npm install methodical
यह मूल रूप से ऊपर बताई गई हर चीज को करता है, जिसमें कुछ विकल्प थोड़े अधिक सख्त होते हैं, और सभी बिना if (typeof x.method === 'function')
बॉयलरप्लेट के लोड के होते हैं ।
उम्मीद है कि कोई इसे उपयोगी पाता है।
यह एक पुराना प्रश्न है, फिर भी यह विषय मुझे ख़राब करना नहीं चाहता।
इंटरफ़ेस को "लागू करने" पर वेब पर और यहाँ के कई जवाबों के अनुसार, मैं एक वैकल्पिक दृश्य सुझाना चाहूंगा:
मैं इंटरफेस की कमी महसूस हो रहा है सबसे जब मैं कई वर्गों है कि व्यवहार इसी तरह (यानी उपयोग कर रहा हूँ एक इंटरफ़ेस को लागू )।
उदाहरण के लिए, मेरे पास एक ईमेल जनरेटर है जो ईमेल अनुभागों को प्राप्त करने की अपेक्षा करता है , जो कि अनुभागों की सामग्री और HTML उत्पन्न करने के लिए "पता" करता है। इसलिए, उन सभी को कुछ प्रकार getContent(id)
और getHtml(content)
विधियों की आवश्यकता होती है।
इंटरफेस के निकटतम पैटर्न (यद्यपि यह अभी भी एक हल है) मैं सोच सकता था कि एक वर्ग का उपयोग कर रहा हूँ जिसे 2 तर्क मिलेंगे, जो 2 इंटरफ़ेस विधियों को परिभाषित करेगा।
इस पैटर्न के साथ मुख्य चुनौती यह है कि static
इसके गुणों को एक्सेस करने के लिए तरीकों को या तो तर्क के रूप में प्राप्त करना है या उदाहरण के रूप में खुद को तर्क देना है। हालांकि ऐसे मामले हैं जिनमें मुझे यह ट्रेड-ऑफ परेशानी के लायक लगता है।
class Filterable {
constructor(data, { filter, toString }) {
this.data = data;
this.filter = filter;
this.toString = toString;
// You can also enforce here an Iterable interface, for example,
// which feels much more natural than having an external check
}
}
const evenNumbersList = new Filterable(
[1, 2, 3, 4, 5, 6], {
filter: (lst) => {
const evenElements = lst.data.filter(x => x % 2 === 0);
lst.data = evenElements;
},
toString: lst => `< ${lst.data.toString()} >`,
}
);
console.log('The whole list: ', evenNumbersList.toString(evenNumbersList));
evenNumbersList.filter(evenNumbersList);
console.log('The filtered list: ', evenNumbersList.toString(evenNumbersList));
अमूर्त इंटरफ़ेस इस तरह
const MyInterface = {
serialize: () => {throw "must implement serialize for MyInterface types"},
print: () => console.log(this.serialize())
}
एक उदाहरण बनाएँ:
function MyType() {
this.serialize = () => "serialized "
}
MyType.prototype = MyInterface
और इसका उपयोग करें
let x = new MyType()
x.print()