2013-04-06 3 views
8

को समझने का प्रयास मैं double-dispatch pattern और कठिन समय होने के लिए प्रयास कर रहा हूं। अंततः मैंने समझने में मदद करने के लिए नमूना कार्यक्रम का प्रयास किया। Here's जिस्ट। लेकिन फिर मैंने इसे without Double dispatch का प्रयास करने का निर्णय लिया और समाधान सामान्य से अधिक भयानक नहीं दिख रहा था। मैं क्या गलत कर रहा हूं?डबल-प्रेषण पैटर्न

संपादित करें: सुझाव के अनुसार, मैंने यह प्रश्न here पोस्ट किया है। रीडायरेक्ट के लिए इस लिंक को चारों ओर रखते हुए।

+0

आपके पास http: // http: //programmers.stackexchange.com/ पर बेहतर भाग्य हो सकता है। हालांकि यह एक दिलचस्प सवाल है, यह वास्तव में स्टैक ओवरफ़्लो के लिए एक अच्छा फिट नहीं है; यह साइट "सही उत्तर" के साथ ठोस प्रश्नों को पसंद करती है। –

+1

मैं असहमत हूं; SO –

उत्तर

17

एकल प्रेषण में --- आप आधुनिक ओओ भाषाओं में जो देखते हैं --- एक विधि एक ऑब्जेक्ट के रन-टाइम प्रकार के आधार पर प्रेषित है। यह डॉट ऑपरेटर (रूबी, जावा, जावास्क्रिप्ट, आदि) या तीर ऑपरेटर (perl, C++) के रूप में दिखाई देता है।

# look, ma single dispatch! 
# method on obj's run-time type that is called 
dentist.work_on(patient) 

डबल प्रेषण, तो, दो वस्तुओं के रन-टाइम प्रकार के आधार पर किया जाएगा। ऐसा कुछ तरीके हैं जो यह देख सकते हैं; और किस वस्तु पर विधि रहनी चाहिए?

# Hmm, this looks weird. 
# Is the method in to dentist.class or patient.class? 
(dentist, patient).do_dentistry() 


# okay, this looks more familiar; the method lives on obj1.class 
# This only works in static-typed languages which support double dispatch 
# in which you declare the type of the method parameters. 
dentist.work_on(patient) 

class Dentist 
    def work_on(Adult patient); ...; end 
    def work_on(Child patient); ...; end 
end 

ग्रोवी जैसी भाषाएं जिनमें एकाधिक प्रेषण ऊपर दिए गए दूसरे उदाहरण को सामान्यीकृत करता है; वे चलाने के लिए कौन सी विधि चुनते हैं, वे सभी पैरामीटर के रन-टाइम प्रकारों पर विचार करते हैं। उदाहरण के लिए this blog post ग्रोवी और एकाधिक प्रेषण के बारे में देखें।

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

class Dentist 
    def work_on(patient) 
     patient.dispatch_work(self) 
    end 
    def work_on_adult(patient) 
     drill_as_hard_as_you_can(patient) 
    end 
    def work_on_child(patient) 
     use_bubble_gum_toothpaste(patient) 
     give_toothbrush_to(patient) 
    end 
end 

class Doctor 
    def work_on(patient) 
     patient.dispatch_work(self) 
    end 
    def work_on_adult(patient) 
     do_checkup(patient) 
    end 
    def work_on_child(patient) 
     assure_presence_of(patient.guardian) 
     ask_questions_to(patient.guardian) 
     do_checkup(patient) 
     give_cheap_toy_to(patient) 
    end 
end 



class Adult 
    def dispatch_work(dentist) 
     dentist.work_on_adult(self) 
    end 
end 

class Child 
    def dispatch_work(dentist) 
     dentist.work_on_child(self) 
    end 
end 

डबल प्रेषण पैटर्न क्या मैं एक निम्न स्तर के पैटर्न कहते हैं क्योंकि अन्य पैटर्न उस पर निर्माण कर रहे हैं है। उदाहरण के लिए, विज़िटर पैटर्न डबल प्रेषण पैटर्न पर भारी निर्भर करता है।


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

class Chicken 
    def make_dispatch dish 
    dish.make_with_chicken self 
    end 
end 

class Beef 
    def make_dispatch dish 
    dish.make_with_beef self 
    end 
end 


module Dish 
    def make meat 
    meat.make_dispatch self 
    end 
end 

class Sandwich 
    include Dish 

    def make_with_chicken chicken 
    puts "Grilled Chicken Sandwich" 
    end 

    def make_with_beef beef 
    puts "Roast Beef Sandwich" 
    end 
end 

class Stew 
    include Dish 

    def make_with_chicken chicken 
    puts "Thai curry" 
    end 

    def make_with_beef beef 
    puts "Beef stew" 
    end 
end 

class Casserole 
    include Dish 

    def make_with_chicken chicken 
    puts "Chicken Pot Pie--or something" 
    end 

    def make_with_beef beef 
    puts "Shepard's Pie" 
    end 
end 

Sandwich.new.make(Chicken.new) 
Stew.new.make(Chicken.new) 
Casserole.new.make(Beef.new) 
+0

पर पूछने के लिए यह एक अच्छा सवाल है, मुझे लगता है कि विज़िटर पैटर्न वास्तव में एकाधिक प्रेषण को लागू करने का एक आम तरीका है। उदाहरण देखें http://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_in_C.2B.2B इसके अलावा आपका दंत चिकित्सक उदाहरण थोड़ा भ्रमित हो सकता है क्योंकि केवल एक दंत चिकित्सक है इसलिए आपको वास्तव में डबल प्रेषण की आवश्यकता नहीं है। :) – Sarien

+0

@ सरीन अच्छा बिंदु, मैंने उदाहरण के लिए एक डॉक्टर जोड़ा है। हाँ आगंतुक डबल प्रेषण करने का एक बहुत ही आम तरीका है। –

संबंधित मुद्दे