वास्तविक दुनिया में बहुरूपता का उपयोग कैसे किया जाता है? [बन्द है]


17

मैं यह समझने की कोशिश कर रहा हूं कि वास्तविक जीवन की परियोजना में बहुरूपता का उपयोग कैसे किया जाता है, लेकिन मैं केवल Animalएक विधि के साथ माता-पिता वर्ग होने के शास्त्रीय उदाहरण (या इसके समान कुछ) पा सकता हूं speak(), और कई बच्चे कक्षाएं जो इस पद्धति को ओवरराइड करते हैं, और अब आप speak()किसी भी चाइल्ड ऑब्जेक्ट पर विधि को कॉल कर सकते हैं, उदाहरण के लिए:

Animal animal;

animal = dog;
animal.speak();

animal = cat;
animal.speak();



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

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

सामान्य तौर पर यदि आप अक्सर विभिन्न प्रकारों को संभालने के लिए ओवरलोड तरीके बना रहे हैं और कोड समान है, या यदि आप if(x is SomeType) DoSomething()अक्सर लिख रहे हैं , तो यह बहुरूपता का उपयोग करने के लायक हो सकता है। मेरे लिए बहुरूपता एक अलग विधि बनाने के लिए एक निर्णय के समान है, अगर मैंने पाया कि मैंने कोड को कुछ बार दोहराया तो मैं इसे आमतौर पर एक विधि में फिर से सम्मिलित करता हूं, और अगर मुझे लगता है कि मैं या तो if object is this type do thisकोड बना रहा हूं, तो यह हो सकता है एक इंटरफ़ेस या वर्ग जोड़ने और जोड़ने लायक।
jrh

जवाबों:


35

धारा बहुरूपता का महान उदाहरण है।

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

इस तरह, स्ट्रीम का उपयोग करने वाले क्लाइंट को यह ध्यान रखने की आवश्यकता नहीं है कि बाइट्स कहां से आते हैं। बस उन्हें क्रम से पढ़ा जा सकता है।

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


2
C ++ जैसी मल्टीपल और वर्चुअल इनहेरिटेंस वाली भाषाओं में, यह उदाहरण "खूंखार हीरे" पैटर्न को भी प्रदर्शित कर सकता है ... बेस स्ट्रीम क्लास से इनपुट और आउटपुट स्ट्रीम कक्षाओं को प्राप्त करके, और I / O स्ट्रीम बनाने के लिए दोनों का विस्तार
gy

2
@gyre और अच्छा किया, हीरे के पैटर्न को "डर" देने का कोई कारण नहीं है। हीरे में विपरीत समकक्ष के बारे में पता होना और इसके साथ नाम के टकराव का कारण नहीं होना आवश्यक है, और एक चुनौती है, और कष्टप्रद है, और हीरे के पैटर्न से बचने का कारण है जहां व्यावहारिक ... लेकिन जब तक यह नहीं फैलता है बस, एक नामकरण सम्मेलन समस्याओं को हल कर सकता है।
केरेन

+1 Streams मेरा सर्वकालिक पसंदीदा बहुरूपता उदाहरण हैं। मैं अब भी लोगों को 'जानवर, स्तनपायी, कुत्ते' के मॉडल को सिखाने की कोशिश नहीं करता, Streamलेकिन बेहतर काम करता हूं।
फराप जूल

@KRyan मैं अपने विचारों को "खूंखार हीरा" कहकर व्यक्त नहीं कर रहा था, मैंने अभी-अभी इसे इस तरह से सुना है। मैं पूरी तरह से सहमत; मुझे लगता है कि यह कुछ ऐसा है जो प्रत्येक डेवलपर को अपने सिर को चारों ओर लपेटने और उचित रूप से उपयोग करने में सक्षम होना चाहिए।
चक्र

@gyre ओह, हाँ, मुझे वास्तव में ऐसा मिला; इसलिए मैंने इसे विरोधाभास के बजाय "अपने विचार" का संकेत देने के लिए शुरू किया।
केरेन

7

एक सामान्य खेल से संबंधित उदाहरण एक आधार वर्ग होगा Entity, जो सामान्य सदस्यों को प्रदान करेगा जैसे draw()या update()

अधिक शुद्ध डेटा उन्मुख उदाहरण के लिए एक आधार वर्ग Serializableएक आम saveToStream()और प्रदान कर सकता है loadFromStream()


6

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

रनटाइम बहुरूपता का एक बहुत ही उच्च-स्तरीय वर्णन यह है कि एक विधि कॉल रनटाइम प्रकार के तर्कों के आधार पर अलग-अलग चीजें करता है: एक विधि कॉल को हल करने के लिए ऑब्जेक्ट स्वयं जिम्मेदार है। यह बड़ी मात्रा में लचीलेपन की अनुमति देता है।

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

void foo() {
  if (isTesting) {
    ... // do mock stuff
  } else {
    ... // do normal stuff
  }
}

यह कोड का पालन करना कठिन बनाता है। विकल्प यह है कि उस फू-ऑपरेशन के लिए एक इंटरफ़ेस शुरू करना और एक सामान्य कार्यान्वयन और उस इंटरफ़ेस का एक नकली कार्यान्वयन लिखना, और रनटाइम में वांछित कार्यान्वयन के लिए "इंजेक्शन" करना। "निर्भरता इंजेक्शन" एक तर्क के रूप में "सही वस्तु को पारित करने" के लिए एक जटिल शब्द है।

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

interface Model {
  def predict(sample) -> (prediction: float, std: float);
}

मेरा एल्गोरिथ्म एक कारखाना फ़ंक्शन लेता है जो एक मॉडल को प्रशिक्षित करता है:

def my_algorithm(..., train_model: (observations) -> Model, ...) {
  ...
  Model model = train_model(observations);
  ...
  y, std = model.predict(x)
  ...
}

अब मेरे पास मॉडल इंटरफ़ेस के विभिन्न कार्यान्वयन हैं और उन्हें एक दूसरे के खिलाफ बेंचमार्क कर सकते हैं। इन कार्यान्वयनों में से एक वास्तव में दो अन्य मॉडल लेता है और उन्हें एक बढ़ाया मॉडल में जोड़ता है। तो इस इंटरफ़ेस के लिए धन्यवाद:

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

जीयूआई में बहुरूपता का एक क्लासिक उपयोग मामला है। GUI ढांचे में जैसे जावा AWT / स्विंग / ... अलग-अलग घटक होते हैं । घटक इंटरफ़ेस / बेस क्लास स्क्रीन पर खुद को पेंट करने या माउस क्लिक पर प्रतिक्रिया करने जैसी क्रियाओं का वर्णन करता है। कई घटक कंटेनर होते हैं जो उप-घटकों का प्रबंधन करते हैं। ऐसे कंटेनर को कैसे आकर्षित किया जा सकता है?

void paint(Graphics g) {
  super.paint(g);
  for (Component child : this.subComponents)
    child.paint(g);
}

यहां, कंटेनर को अग्रिम में सटीक प्रकार के सब-कॉम्प्लेक्टर्स के बारे में जानने की आवश्यकता नहीं है - जब तक वे Componentइंटरफ़ेस के अनुरूप होते हैं , कंटेनर बस पॉलीमॉर्फिक paint()विधि को कॉल कर सकता है । यह मुझे मनमाने ढंग से नए घटकों के साथ AWT वर्ग पदानुक्रम का विस्तार करने की स्वतंत्रता देता है।

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

लेकिन हर डिज़ाइन को पॉलीमॉर्फिज़्म (यूनिट टेस्टिंग के लिए निर्भरता इंजेक्शन को सक्षम करने से परे) का उपयोग करने की आवश्यकता नहीं है, जो वास्तव में अच्छा उपयोग मामला है)। अधिकांश समस्याएं अन्यथा बहुत स्थैतिक हैं। एक परिणाम के रूप में, वर्गों और विधियों का उपयोग अक्सर बहुरूपता के लिए नहीं किया जाता है, लेकिन बस सुविधाजनक नामस्थान के रूप में और सुंदर विधि कॉल सिंटैक्स के लिए किया जाता है। जैसे कई डेवलपर्स account.getBalance()एक बड़े पैमाने पर समकक्ष फ़ंक्शन कॉल की तरह विधि कॉल पसंद करते हैं Account_getBalance(account)। यह पूरी तरह से ठीक दृष्टिकोण है, यह सिर्फ इतना है कि कई "विधि" कॉल का बहुरूपता से कोई लेना-देना नहीं है।


6

अधिकांश UI टूलकिट में आपको बहुत सारी विरासत और बहुरूपता दिखाई देती हैं।

उदाहरण के लिए, JavaFX यूआई टूलकिट में, Buttonसे विरासत में मिली ButtonBaseहै, जिसमें से विरासत में मिली Labeledहै, जिसमें से विरासत में मिली Controlहै, जिसमें से विरासत में मिली Regionहै, जिसमें से विरासत में मिली Parentहै, जिसमें से विरासत में मिली Nodeहै जो inherits से Object। कई परतें पिछले वाले से कुछ तरीकों को ओवरराइड करती हैं।

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

UI टूलकिट का एक बहुत ही वास्तविक विश्व महत्व है, जो उन्हें अकादमिक और व्यावहारिक दोनों कारणों से पढ़ाने के लिए उपयोगी बनाता है।

हालांकि, यूआई टूलकिट्स में एक महत्वपूर्ण खामी भी है: वे विशाल होते हैं । जब एक नियोफाइट सॉफ्टवेयर इंजीनियर एक सामान्य यूआई फ्रेमवर्क के आंतरिक कामकाज को समझने की कोशिश करता है, तो वे अक्सर सौ वर्गों से अधिक का सामना करेंगे , उनमें से अधिकांश बहुत गूढ़ उद्देश्यों की सेवा करते हैं। "क्या बिल्ली एक है ReadOnlyJavaBeanLongPropertyBuilder? यह महत्वपूर्ण है? मैं क्या है समझने के लिए यह करने के लिए क्या अच्छा है?" शुरुआती आसानी से उस खरगोश के छेद में खो सकते हैं। इसलिए वे या तो आतंक में भाग सकते हैं या सतह पर रह सकते हैं जहां वे सिर्फ वाक्य रचना सीखते हैं और वास्तव में हुड के नीचे क्या हो रहा है इसके बारे में बहुत मुश्किल नहीं सोचने की कोशिश करते हैं।


3

हालांकि यहां पहले से ही अच्छे उदाहरण हैं, एक अन्य को उपकरणों के साथ जानवरों को बदलना है:

  • Deviceहो सकता है powerOn(), powerOff(), setSleep()और कर सकते हैं getSerialNumber()
  • SensorDeviceसभी ऐसा कर सकते हैं, और इस तरह के रूप में बहुरूपी कार्यों प्रदान करते हैं getMeasuredDimension(), getMeasure(), alertAt(threashhold)और autoTest()
  • बेशक, getMeasure()तापमान सेंसर, लाइट डिटेक्टर, साउंड डिटेक्टर या वॉल्यूमेट्रिक सेंसर के लिए उसी तरह से लागू नहीं किया जाएगा। और हां, इनमें से प्रत्येक अधिक विशिष्ट सेंसर में कुछ अतिरिक्त कार्य उपलब्ध हो सकते हैं।

2

प्रस्तुति एक बहुत ही सामान्य अनुप्रयोग है, शायद सबसे आम एक है जिसे ToString ()। जो मूल रूप से Animal.Speak है (): आप खुद को प्रकट करने के लिए एक ऑब्जेक्ट बताते हैं।

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


2

बहुरूपता का मेरा पहला व्यावहारिक उपयोग जावा में हीप का कार्यान्वयन था।

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

abstract class Heap {  

 abstract boolean compare ( int x , int y );

 boolean insert(int x ) { ... }

 int removeTop() { ... }
}

इसलिए जब मुझे मैक्सहैप और मिनहैप चाहिए था तो मैं सिर्फ विरासत का उपयोग कर सकता था।

class MaxHeap extends Heap {

   MaxHeap(int maxSize) {super(maxSize);}

   @Override
   boolean compare(int x, int y) {
       return x>y; // x<y for minHeap
   }
}

1

यहां वेब ऐप / डेटाबेस टेबल पॉलीमॉर्फिज़्म के लिए एक वास्तविक जीवन परिदृश्य है :

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

रेल में मैं अपने मॉडलों को इस तरह डिजाइन करूंगा:

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end

class User < ApplicationRecord
  has_many :pictures, as: :imageable
end

class Product < ApplicationRecord
  has_many :pictures, as: :imageable
end

और picturesतालिका बनाने के लिए एक डेटाबेस माइग्रेशन :

class CreatePictures < ActiveRecord::Migration[5.0]
  def change
    create_table :pictures do |t|
      t.string  :name
      t.integer :imageable_id
      t.string  :imageable_type
      t.timestamps
    end

    add_index :pictures, [:imageable_type, :imageable_id]
  end
end

कॉलम imageable_idऔर imageable_typeरेल द्वारा आंतरिक रूप से उपयोग किया जाता है। मूल रूप से, imageable_typeवर्ग ( "User"और "Product", आदि) का नाम रखता है , और imageable_idसंबद्ध रिकॉर्ड की आईडी है। तो imageable_type = "User"और imageable_id = 1में रिकॉर्ड किया जाएगा usersके साथ तालिकाid = 1

यह हमें user.picturesउपयोगकर्ता की तस्वीरों का उपयोग करने के साथ-साथ product.picturesउत्पाद की तस्वीरें प्राप्त करने की अनुमति देता है । फिर, चित्र-संबंधी व्यवहार के सभी में समझाया जाता हैPhoto वर्ग (और प्रत्येक मॉडल के लिए एक अलग वर्ग नहीं है जिसे फ़ोटो की आवश्यकता होती है), इसलिए चीजें डीआरवाई रखी जाती हैं।

अधिक पढ़ना: बहुरूपी संघों को रोकता है


0

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

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

जो मैंने ऊपर वर्णित किया है वह रनटाइम बहुरूपता का एक उदाहरण है, जबकि विधि अधिभार संकलन समय के बहुरूपता का एक उदाहरण है जहां i / p और o / p पैरामीटर के प्रकार पर निर्भर करता है और पैरामीटर्स के प्रकार और मापदंडों की संख्या को सही समय पर जटिल विधि से बांधता है।

आशा है कि यह स्पष्ट करता है।

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