रूबी में जावा इंटरफेस क्या है?


104

क्या हम रूबी में इंटरफेस को उजागर कर सकते हैं जैसे हम जावा में करते हैं और इंटरफ़ेस द्वारा परिभाषित तरीकों को लागू करने के लिए रूबी मॉड्यूल या कक्षाएं लागू करते हैं।

एक तरीका यह है कि विरासत और method_missing का उपयोग उसी को प्राप्त करने के लिए किया जाए लेकिन क्या कोई और उपयुक्त तरीका उपलब्ध है?



6
आपको दोगुना पूछना चाहिए कि आपको इसकी आवश्यकता क्यों है। अक्सर पर्याप्त इंटरफेस का उपयोग सिर्फ लानत चीज को संकलित करने के लिए किया जाता है जो रूबी में कोई समस्या नहीं है।
अर्निस लैप्स

1
इस प्रश्न को [[ रूबी में, C # में एक इंटरफ़ेस के बराबर क्या है? ] ( StackOverflow.Com/q/3505521/#3507460 )।
जोर्ग डब्ल्यू मित्तग

2
मुझे इसकी आवश्यकता क्यों है? मैं कुछ ऐसा लागू करना चाहता हूं जिसे आप "संस्करण" के रूप में कह सकते हैं जो दस्तावेजों / फाइलों को संस्करण योग्य बनाता है, लेकिन क्या .... का उपयोग करने योग्य है। उदाहरण के लिए, मैं SVN या CVS जैसे मौजूदा रिपॉजिटरी सॉफ्टवेयर्स का उपयोग करके इसे संस्करण योग्य बना सकता हूं। जो भी अनुरक्षण तंत्र मैं इसे चुनता हूं उसे कुछ बुनियादी न्यूनतम कार्य प्रदान करने चाहिए। मैं किसी भी नए अंतर्निहित रिपोजिटरी कार्यान्वयन द्वारा इन नंगे न्यूनतम कार्यों के कार्यान्वयन को लागू करने के लिए इंटरफ़ेस जैसी चीज़ का उपयोग करना चाहता हूं।
crazycrv

अपनी POODR पुस्तक में Sandi Metz दस्तावेज़ इंटरफेस के लिए परीक्षण का उपयोग करता है। यह पुस्तक पढ़ने के लिए वास्तव में लायक है। 2015 तक मैं कहूंगा कि @ aleksander-pohl उत्तर सबसे अच्छा है।
ग्रेग डान

जवाबों:


86

रूबी के पास किसी अन्य भाषा की तरह ही इंटरफेसेस हैं।

ध्यान दें कि आपको इंटरफ़ेस की अवधारणा को भ्रमित न करने के लिए सावधान रहना होगा , जो एक इकाई के जिम्मेदारियों, गारंटी और प्रोटोकॉल का एक सार विनिर्देश है, जिसकी अवधारणा के साथ interfaceजावा, C # और VB.NET प्रोग्रामिंग में एक कीवर्ड है। भाषाओं। रूबी में, हम हर समय पूर्व का उपयोग करते हैं, लेकिन बाद वाला मौजूद नहीं है।

दोनों में अंतर करना बहुत जरूरी है। इंटरफ़ेस क्या महत्वपूर्ण है , नहीं interfaceinterfaceआप उपयोगी काफी कुछ भी नहीं बताता है। जावा में मार्कर इंटरफेस की तुलना में कुछ भी बेहतर प्रदर्शन नहीं करता है, जो ऐसे इंटरफेस हैं जिनमें कोई सदस्य नहीं है: बस एक नज़र डालें java.io.Serializableऔर java.lang.Cloneable; उन दो का interfaceमतलब बहुत अलग चीजें हैं, फिर भी उनके पास एक ही हस्ताक्षर हैं।

इसलिए, अगर दो interfaceका मतलब है कि अलग-अलग चीजें हैं, एक ही हस्ताक्षर है, तो वास्तव में interfaceआपको क्या गारंटी है?

एक और अच्छा उदाहरण:

package java.util;

interface List<E> implements Collection<E>, Iterable<E> {
    void add(int index, E element)
        throws UnsupportedOperationException, ClassCastException,
            NullPointerException, IllegalArgumentException,
            IndexOutOfBoundsException;
}

क्या है इंटरफ़ेस की java.util.List<E>.add?

  • कि संग्रह की लंबाई घटती नहीं है
  • इससे पहले कि संग्रह में थे सभी आइटम अभी भी वहाँ हैं
  • यह elementसंग्रह में है

और उनमें से कौन वास्तव में दिखाता है interface? कोई नहीं! इसमें ऐसा कुछ भी नहीं है interfaceजो कहता है कि Addविधि को बिल्कुल भी जोड़ना चाहिए , यह सिर्फ एक तत्व को संग्रह से निकाल सकता है ।

यह उस का पूरी तरह से मान्य कार्यान्वयन है interface:

class MyCollection<E> implements java.util.List<E> {
    void add(int index, E element)
        throws UnsupportedOperationException, ClassCastException,
            NullPointerException, IllegalArgumentException,
            IndexOutOfBoundsException {
        remove(element);
    }
}

एक और उदाहरण: जहां java.util.Set<E>यह वास्तव में कहता है कि यह है, आप जानते हैं, एक सेट ? कहीं भी नहीं! या अधिक सटीक, प्रलेखन में। अंग्रेजी में।

interfacesजावा और .NET दोनों से बहुत अधिक मामलों में , सभी प्रासंगिक जानकारी वास्तव में डॉक्स में हैं, न कि प्रकारों में। इसलिए, यदि प्रकार आपको कुछ भी दिलचस्प नहीं बताते हैं, तो उन्हें क्यों रखें? सिर्फ प्रलेखन के लिए क्यों न रहें? और ठीक यही रूबी करती है।

ध्यान दें कि अन्य भाषाएं हैं जिनमें इंटरफ़ेस को वास्तव में सार्थक तरीके से वर्णित किया जा सकता है। हालाँकि, वे भाषाएँ आमतौर पर उस निर्माण को नहीं कहते हैं जो इंटरफ़ेस का वर्णन करता है " interface", वे इसे कहते हैं type। एक निर्भर-टाइप की गई प्रोग्रामिंग भाषा में, आप उदाहरण के लिए, उन गुणों को व्यक्त कर सकते हैं जो एक sortफ़ंक्शन मूल के समान लंबाई का एक संग्रह लौटाते हैं, जो मूल में है हर तत्व भी सॉर्ट किए गए संग्रह में है और कोई बड़ा तत्व नहीं है एक छोटे तत्व से पहले दिखाई देता है।

तो, संक्षेप में: रूबी एक जावा के बराबर नहीं है interface। यह है , तथापि, एक बराबर एक जावा के लिए है इंटरफेस है, और यह वास्तव में जावा में के रूप में ही है: प्रलेखन।

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

विशेष रूप से, रूबी में, किसी वस्तु का इंटरफ़ेस निर्धारित किया जाता है कि वह क्या कर सकता है , न कि classवह क्या है, या क्या moduleमिलाता है। किसी भी वस्तु को जिस <<विधि से जोड़ा जा सकता है। यह यूनिट परीक्षणों में बहुत उपयोगी है, जहां आप बस एक Arrayया Stringअधिक जटिल के बजाय पास कर सकते हैं Logger, भले ही Arrayऔर इस तथ्य के अलावा Loggerएक स्पष्ट रूप interfaceसे साझा न करें कि उनके पास एक विधि है <<

एक अन्य उदाहरण है StringIO, जो औजार एक ही इंटरफ़ेस के रूप में IOहै और इस तरह के एक बड़े हिस्से इंटरफेस की File, लेकिन अलावा किसी आम पूर्वज साझा किए बिना Object


282
जबकि एक अच्छा पढ़ा मैं जवाब है कि उपयोगी नहीं मिल रहा है। यह interfaceबेकार के एक शोध प्रबंध की तरह पढ़ता है, इसके उपयोग की बात याद आती है। यह कहना आसान होगा कि रूबी गतिशील रूप से टाइप की गई है और इसका एक अलग ध्यान मन में है और आईओसी जैसी अवधारणाओं को अनावश्यक / अवांछित बना देता है। यदि आप अनुबंध द्वारा डिजाइन करने के लिए उपयोग किए जाते हैं तो यह एक कठिन बदलाव है। कुछ रेलों से लाभ हो सकता है, जिन्हें कोर टीम ने महसूस किया है जैसा कि आप नवीनतम संस्करणों पर देख सकते हैं।
गोलियत

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

9
interface निर्माण वास्तव में केवल स्थिर टाइप किया एकल विरासत भाषाओं में एक ही (जैसे इलाज के रूप में विभिन्न प्रकार के इलाज के लिए की जरूरत है LinkedHashSetऔर ArrayListदोनों एक के रूप में Collection), यह काफी कुछ भी नहीं के साथ करते है इंटरफ़ेस इस जवाब से पता चलता है के रूप में। रूबी को वैधानिक रूप से टाइप नहीं किया गया है, इसलिए निर्माण की कोई आवश्यकता नहीं है ।
एस्लेइजा

16
मैंने इसे "कुछ इंटरफेस का कोई मतलब नहीं है, इसलिए पढ़ा है, इसलिए इंटरफेस खराब हैं। आप इंटरफेस का उपयोग क्यों करना चाहते हैं?"। यह सवाल का जवाब नहीं देता है और स्पष्ट रूप से किसी ऐसे व्यक्ति की तरह लगता है जो यह नहीं समझता है कि इंटरफेस क्या हैं और उनके लाभ हैं।
Oddman

13
लिस्ट इंटरफ़ेस की अमान्यता के बारे में आपका तर्क एक विधि का उल्लेख करता है जो "ऐड" नामक फ़ंक्शन में एक निष्कासन करता है, एक रिडक्टियो विज्ञापन एब्सर्डम तर्क का एक उत्कृष्ट उदाहरण है। विशेष रूप से यह किसी भी भाषा में (माणिक शामिल) संभव है कि एक विधि लिखी जाए जो अपेक्षा से अलग है। यह "इंटरफ़ेस" के खिलाफ एक वैध तर्क नहीं है यह सिर्फ बुरा कोड है।
जस्टिन

61

Rspec के "साझा उदाहरण" आज़माएँ:

https://www.relishapp.com/rspec/rspec-core/v/3-5/docs/example-groups/shared-examples

आप अपने इंटरफ़ेस के लिए एक युक्ति लिखते हैं और फिर प्रत्येक कार्यान्वयनकर्ता की युक्ति में एक पंक्ति डालते हैं, जैसे।

it_behaves_like "my interface"

पूरा उदाहरण:

RSpec.shared_examples "a collection" do
  describe "#size" do
    it "returns number of elements" do
      collection = described_class.new([7, 2, 4])
      expect(collection.size).to eq(3)
    end
  end
end

RSpec.describe Array do
  it_behaves_like "a collection"
end

RSpec.describe Set do
  it_behaves_like "a collection"
end

अद्यतन : आठ साल बाद (2020) रूबी को अब शर्बत के माध्यम से सांख्यिकीय रूप से टाइप किए गए इंटरफेस के लिए समर्थन मिला है। शर्बत डॉक्स में सार कक्षाएं और इंटरफेस देखें ।


17
मेरा मानना ​​है कि यह स्वीकृत उत्तर होना चाहिए। यह वह प्रकार है जिसमें अधिकांश प्रकार की कमजोर भाषाएँ जावा को इंटरफेस की तरह प्रदान कर सकती हैं। स्वीकार किए जाते हैं, बताते हैं कि रूबी के पास इंटरफेस क्यों नहीं है, उन्हें कैसे अनुकरण करना है।
SystematicFrank

1
मैं सहमत हूं, इस जवाब ने मुझे एक जावा डेवलपर के रूप में अधिक मदद की, जो कि ऊपर दिए गए उत्तर की तुलना में रूबी के लिए आगे बढ़ रहा है।
कैम

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

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

41

क्या हम रूबी में इंटरफेस को उजागर कर सकते हैं जैसे हम जावा में करते हैं और इंटरफ़ेस द्वारा परिभाषित तरीकों को लागू करने के लिए रूबी मॉड्यूल या कक्षाओं को लागू करते हैं।

रूबी में वह कार्यक्षमता नहीं है। सिद्धांत रूप में, उन्हें इसकी आवश्यकता नहीं है क्योंकि रूबी डक टाइपिंग कहती है

कुछ दृष्टिकोण हैं जिन्हें आप ले सकते हैं।

अपवादों को बढ़ाने वाले कार्यान्वयन लिखें; यदि कोई उपवर्ग अनिमित पद्धति का उपयोग करने का प्रयास करता है, तो वह विफल हो जाएगा

class CollectionInterface
  def add(something)
    raise 'not implemented'
  end
end

उपरोक्त के साथ, आपको परीक्षण कोड लिखना चाहिए जो आपके अनुबंधों को लागू करता है (यहां अन्य पोस्ट गलत तरीके से इंटरफ़ेस क्यों कहते हैं )

यदि आप अपने आप को हर समय ऊपर की तरह शून्य तरीके से लिखते हुए पाते हैं, तो एक सहायक मॉड्यूल लिखें जो इसे कैप्चर करता है

module Interface
  def method(name)
    define_method(name) { |*args|
      raise "interface method #{name} not implemented"
    }
  end
end

class Collection
  extend Interface
  method :add
  method :remove
end

अब, रूबी मॉड्यूल के साथ उपरोक्त गठबंधन करें और आप जो चाहते हैं उसके करीब हैं ...

module Interface
  def method(name)
    define_method(name) { |*args|
      raise "interface method #{name} not implemented"
    }
  end
end

module Collection
  extend Interface
  method :add
  method :remove
end

col = Collection.new # <-- fails, as it should

और फिर आप कर सकते हैं

class MyCollection
  include Collection

  def add(thing)
    puts "Adding #{thing}"
  end
end

c1 = MyCollection.new
c1.add(1)     # <-- output 'Adding 1'
c1.remove(1)  # <-- fails with not implemented

मुझे एक बार फिर से जोर देने दें: यह एक अल्पविकसित है, क्योंकि रूबी में सब कुछ रनटाइम पर होता है; कोई संकलन समय जाँच नहीं है। यदि आप इसे परीक्षण के साथ जोड़ते हैं, तो आपको त्रुटियों को उठाने में सक्षम होना चाहिए। इससे भी आगे, यदि आप उपरोक्त को आगे ले जाते हैं, तो आप शायद एक इंटरफ़ेस लिखने में सक्षम हो सकते हैं जो पहली बार कक्षा पर जाँच करता है कि उस कक्षा का एक ऑब्जेक्ट बनाया गया है; अपने परीक्षणों को कॉलिंग जितना ही सरल बना रहे हैं MyCollection.new... हाँ, ऊपर से :)


ठीक है, लेकिन अगर आपका संग्रह = MyCollection इंटरफ़ेस में परिभाषित कोई विधि लागू नहीं करता है जो पूरी तरह से काम करता है, तो आप यह सुनिश्चित नहीं कर सकते कि आपके ऑब्जेक्ट में केवल इंटरफ़ेस विधियां हैं।
जोएल एज़ेमर

यह बहुत बढ़िया है, धन्यवाद। बत्तख टाइपिंग ठीक है, लेकिन कभी-कभी इसका अच्छा अन्य देवों को स्पष्ट रूप से संवाद करना है कि एक इंटरफ़ेस को कैसे व्यवहार करना चाहिए।
मिरोडिन्हो

10

जैसा कि यहां सभी ने कहा, माणिक के लिए कोई इंटरफ़ेस प्रणाली नहीं है। लेकिन आत्मनिरीक्षण के माध्यम से, आप इसे खुद को काफी आसानी से लागू कर सकते हैं। यहाँ एक सरल उदाहरण है जिसे शुरू करने में आपकी मदद करने के लिए कई तरीकों से सुधार किया जा सकता है:

class Object
  def interface(method_hash)
    obj = new
    method_hash.each do |k,v|
      if !obj.respond_to?(k) || !((instance_method(k).arity+1)*-1)
        raise NotImplementedError, "#{obj.class} must implement the method #{k} receiving #{v} parameters"
      end
    end
  end
end

class Person
  def work(one,two,three)
    one + two + three
  end

  def sleep
  end

  interface({:work => 3, :sleep => 0})
end

व्यक्ति पर घोषित तरीकों में से एक को हटाने या इसे बदलने से तर्कों की संख्या बढ़ जाएगी NotImplementedError


5

जावा तरीके में इंटरफेस जैसी कोई चीज नहीं है। लेकिन अन्य चीजें हैं जो आप माणिक में आनंद ले सकते हैं।

यदि आप कुछ प्रकार के प्रकार और इंटरफ़ेस को लागू करना चाहते हैं - ताकि वस्तुओं की जांच की जा सके कि क्या उनके पास कुछ तरीके / संदेश हैं जिनकी आपको आवश्यकता है -, तो आप रूबीकंट्रैक्ट्स पर एक नज़र डाल सकते हैं । यह PyProtocols के समान एक तंत्र को परिभाषित करता है । माणिक में टाइप चेकिंग के बारे में एक ब्लॉग यहाँ है

वर्णित दृष्टिकोण जीवित परियोजनाएं नहीं हैं, हालांकि लक्ष्य पहले से अच्छा लग रहा है, ऐसा लगता है कि अधिकांश रूबी डेवलपर्स सख्त प्रकार की जांच के बिना रह सकते हैं। लेकिन माणिक का लचीलापन प्रकार की जाँच को लागू करने में सक्षम बनाता है।

यदि आप कुछ व्यवहारों द्वारा वस्तुओं या वर्गों (रूबी में एक ही चीज) का विस्तार करना चाहते हैं या कुछ हद तक कई विरासतों का माणिक तरीका है, includeया extendतंत्र का उपयोग करें । साथ includeआप एक वस्तु में एक और वर्ग या मॉड्यूल से तरीकों में शामिल कर सकते हैं। extendआप एक वर्ग के साथ व्यवहार जोड़ सकते हैं, ताकि उसके उदाहरणों में जोड़े गए तरीके होंगे। हालांकि यह बहुत ही संक्षिप्त विवरण था।

मेरी राय जावा इंटरफ़ेस की जरूरत को हल करने का सबसे अच्छा तरीका है रूबी ऑब्जेक्ट मॉडल ( उदाहरण के लिए डेव थॉमस व्याख्यान देखें ) को समझना । संभवतः आप जावा इंटरफेस के बारे में भूल जाएंगे। या आपके पास अपने समय पर एक असाधारण आवेदन है।


उन डेव थॉमस व्याख्यान एक paywall के पीछे हैं।
पर्पलजकेट

5

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

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

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


3

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

इस तरह परिभाषित तरीकों के साथ अपने इंटरफेस पर विचार करें

class FooInterface
  class NotDefinedMethod < StandardError; end
  REQUIRED_METHODS = %i(foo).freeze
  def initialize(object)
    @object = object
    ensure_method_are_defined!
  end
  def method_missing(method, *args, &block)
    ensure_asking_for_defined_method!(method)
    @object.public_send(method, *args, &block)
  end
  private
  def ensure_method_are_defined!
    REQUIRED_METHODS.each do |method|
      if !@object.respond_to?(method)
        raise NotImplementedError, "#{@object.class} must implement the method #{method}"
      end
    end
  end
  def ensure_asking_for_defined_method!(method)
    unless REQUIRED_METHODS.include?(method)
      raise NotDefinedMethod, "#{method} doesn't belong to Interface definition"
    end
  end
end

तब आप कम से कम इंटरफ़ेस अनुबंध के साथ एक वस्तु लिख सकते हैं:

class FooImplementation
  def foo
    puts('foo')
  end
  def bar
    puts('bar')
  end
end

आप अपने इंटरफ़ेस के माध्यम से अपने ऑब्जेक्ट को सुरक्षित रूप से कॉल कर सकते हैं यह सुनिश्चित करने के लिए कि आप इंटरफ़ेस क्या परिभाषित करते हैं

#  > FooInterface.new(FooImplementation.new).foo
# => foo

#  > FooInterface.new(FooImplementation.new).bar
# => FooInterface::NotDefinedMethod: bar doesn't belong to Interface definition

और आप अपनी सभी इंटरफ़ेस विधियों को लागू करने के लिए अपनी वस्तु को सुनिश्चित कर सकते हैं

class BadFooImplementation
end

#  > FooInterface.new(BadFooImplementation.new)
# => NotImplementedError: BadFooImplementation must implement the method foo

2

मैंने अपनी अतिरिक्त जरूरतों के लिए कार्लोसम के जवाब पर थोड़ा विस्तार किया है। यह इंटरफ़ेस क्लास में कुछ अतिरिक्त प्रवर्तन और विकल्प जोड़ता है: required_variableऔर optional_variableजो डिफ़ॉल्ट मान का समर्थन करता है।

मुझे यकीन नहीं है कि आप इस मेटा प्रोग्रामिंग का उपयोग बहुत बड़ी चीज़ के साथ करना चाहेंगे।

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

चेतावनी इस विधि केवल कोड की बुला पर एक त्रुटि फेंकता है। रनटाइम से पहले उचित प्रवर्तन के लिए टेस्ट की आवश्यकता होगी।

कोड उदाहरण

interface.rb

module Interface
  def method(name)
    define_method(name) do
      raise "Interface method #{name} not implemented"
    end
  end

  def required_variable(name)
    define_method(name) do
      sub_class_var = instance_variable_get("@#{name}")
      throw "@#{name} must be defined" unless sub_class_var
      sub_class_var
    end
  end

  def optional_variable(name, default)
    define_method(name) do
      instance_variable_get("@#{name}") || default
    end
  end
end

plugin.rb

मैंने दिए गए पैटर्न का उपयोग करने के लिए मैंने सिंगलटन लाइब्रेरी का उपयोग किया है। इस तरह से कोई भी उपवर्ग इस "इंटरफ़ेस" को लागू करते समय सिंगलटन लाइब्रेरी को विरासत में देता है।

require 'singleton'

class Plugin
  include Singleton

  class << self
    extend Interface

    required_variable(:name)
    required_variable(:description)
    optional_variable(:safe, false)
    optional_variable(:dependencies, [])

    method :run
  end
end

my_plugin.rb

मेरी जरूरतों के लिए यह आवश्यक है कि "इंटरफ़ेस" को लागू करने वाला वर्ग इसे उप-वर्गित करे।

class MyPlugin < Plugin

  @name = 'My Plugin'
  @description = 'I am a plugin'
  @safe = true

  def self.run
    puts 'Do Stuff™'
  end
end

2

अपने आप में रूबी जावा में इंटरफेस के बराबर नहीं है।

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

इसे कहते हैं class_interface

यह काफी सरलता से काम करता है। सबसे पहले मणि को स्थापित करें gem install class_interfaceया इसे अपने मणिफाइल और रंड में जोड़ें bundle install

एक इंटरफ़ेस परिभाषित करना:

require 'class_interface'

class IExample
  MIN_AGE = Integer
  DEFAULT_ENV = String
  SOME_CONSTANT = nil

  def self.some_static_method
  end

  def some_instance_method
  end
end

उस इंटरफ़ेस को लागू करना:

class MyImplementation
  MIN_AGE = 21
  DEFAULT_ENV = 'dev' 
  SOME_CONSTANT = 'some_value'

  def specific_method
    puts "very specific"
  end

  def self.some_static_method
    puts "static method is implemented!"
  end

  def some_instance_method
    # implementation
  end

  def self.another_methods
    # implementation
  end

  implements IExample
end

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

"इम्प्लीमेंट्स" विधि को एक वर्ग की अंतिम पंक्ति में बुलाया जाना चाहिए, क्योंकि यह वह कोड पोजीशन है जहां ऊपर लागू किए गए तरीकों की पहले से जाँच की जाती है।

और अधिक: https://github.com/magynhard/class_interface


0

मुझे एहसास हुआ कि मैं उन वस्तुओं पर सुरक्षा जांच के लिए "लागू नहीं हुई त्रुटि" पैटर्न का उपयोग कर रहा था जो मुझे एक विशिष्ट व्यवहार चाहिए था। मूल रूप से इस तरह के एक इंटरफेस का उपयोग करने की अनुमति देता है कि एक मणि लिखना समाप्त हो गया:

require 'playable' 

class Instrument 
  implements Playable
end

Instrument.new #will throw: Interface::Error::NotImplementedError: Expected Instrument to implement play for interface Playable

यह विधि तर्कों के लिए जाँच नहीं करता है । यह संस्करण के रूप में करता है 0.2.0Https://github.com/bluegod/rint पर अधिक विस्तृत उदाहरण

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