রুবি বনাম __send__ প্রেরণ করুন


151

আমি এর ধারণাটি বুঝতে পেরেছি some_instance.sendতবে কেন আপনি এটিকে উভয় উপায়ে কল করতে পারেন তা বোঝার চেষ্টা করছি। রুবি কোয়ানস বোঝায় যে একই জিনিসটি করার বিভিন্ন উপায় সরবরাহ করার বাইরেও কিছু কারণ রয়েছে। ব্যবহারের দুটি উদাহরণ এখানে দেওয়া হয়েছে:

class Foo
  def bar?
    true
  end
end

foo = Foo.new
foo.send(:bar?)
foo.__send__(:bar?)

এই সম্পর্কে কারও কোন ধারণা আছে?

উত্তর:


242

কিছু ক্লাস (উদাহরণস্বরূপ স্ট্যান্ডার্ড লাইব্রেরির সকেট ক্লাস) তাদের নিজস্ব sendপদ্ধতিটি সংজ্ঞায়িত করে যার সাথে কিছুই করার নেই Object#send। সুতরাং আপনি যদি কোনও শ্রেণীর অবজেক্টের সাথে কাজ করতে চান তবে আপনার ব্যবহার করা দরকার__send__ নিরাপদ দিকে থাকা প্রয়োজন।

এখন যে প্রশ্নটি ছেড়ে দেয়, কেন আছে sendএবং ঠিক নেই __send__। যদি কেবল __send__নামটি থাকে তবে sendঅন্য কোনও বিভ্রান্তি ছাড়াই অন্যান্য শ্রেণি দ্বারা এটি ব্যবহার করা যেতে পারে। এর কারণটি হ'ল sendপ্রথমে বিদ্যমান ছিল এবং কেবলমাত্র পরে বোঝা গিয়েছিল যে নামটি sendঅন্যান্য ক্ষেত্রেও কার্যকরভাবে ব্যবহৃত হতে পারে, তাই যুক্ত __send__করা হয়েছিল (এটি একই জিনিস যা হয়েছিল idএবং object_idপথে হয়েছিল) happened


8
এছাড়াও, বেসিকঅবজেক্ট (রুবি 1.9 তে প্রবর্তিত) কেবল আছে __send__, নেই send
অ্যান্ড্রু মার্শাল

ভাল উত্তর. এটি উল্লেখ করা থাকলে আরও ভাল হতে পারে public_send, যা প্রায়শই sendযাইহোক ভাল।
মার্ক-আন্দ্রে লাফোর্টুন

31

আপনার যদি সত্যিইsend সাধারণত এটির মতো আচরণ করার দরকার হয় তবে আপনার ব্যবহার করা উচিত __send__, কারণ এটি (এটি করা উচিত নয়) ওভাররেড করা হবে না। __send__ক্লাসটি কীভাবে পরিচালনা করা হচ্ছে তা কী কী পদ্ধতিতে সংজ্ঞায়িত করে তা আপনি যখন জানেন না তখন ব্যবহার করা অধিবিদ্যামূলকভাবে বিশেষভাবে কার্যকর। এটি ওভাররাইড করতে পারে send

ঘড়ি:

class Foo
  def bar?
    true
  end

  def send(*args)
    false
  end
end

foo = Foo.new
foo.send(:bar?)
# => false
foo.__send__(:bar?)
# => true

আপনি যদি ওভাররাইড করে থাকেন তবে __send__রুবি একটি সতর্কতা প্রকাশ করবে:

সতর্কতা: f __send__ 'পুনঃনির্ধারণ গুরুতর সমস্যা হতে পারে

কিছু ক্ষেত্রে যেখানে এটি ওভাররাইড করা কার্যকর sendহবে সেখানে সেই নামটি যথাযথ যেমন ম্যাসেজ পাসিং, সকেট ক্লাস ইত্যাদি is


9

__send__ বিদ্যমান তাই এটি দুর্ঘটনার দ্বারা অতিরিক্ত লেখা যায় না।

কেন sendবিদ্যমান তা: আমি অন্য কারও পক্ষে কথা বলতে পারছি না, তবে object.send(:method_name, *parameters)তার চেয়ে ভাল লাগছে object.__send__(:method_name, *parameters), তাই আমার ব্যবহারের প্রয়োজনsend না হলে আমি ব্যবহার করি ।__send__


6

অন্যরা আপনাকে ইতিমধ্যে যা বলেছে সেগুলি বাদ দিয়ে sendএবং __send__এটি একই পদ্ধতির দুটি উপকরণ বলে কী উত্সাহ দেয়, আপনি তৃতীয়টির সাথে আগ্রহী হতে পারেন, কিছুটা ভিন্ন সম্ভাবনাও যা public_send। উদাহরণ:

A, B, C = Module.new, Module.new, Module.new
B.include A #=> error -- private method
B.send :include, A #=> bypasses the method's privacy
C.public_send :include, A #=> does not bypass privacy

আপডেট: যেহেতু রুবি ২.১, Module#includeএবং Module#extendপদ্ধতিগুলি সর্বজনীন হয়, তাই উপরের উদাহরণটি আর কাজ করবে না।


0

প্রেরণ, __send__এবং পাবলিক_সেন্ডের মধ্যে প্রধান পার্থক্যটি নিম্নরূপ।

  1. __send__অবজেক্টের পদ্ধতিতে কল করার জন্য প্রযুক্তিগতভাবে প্রেরণ করুন এবং একইরকম, তবে মূল পার্থক্য হ'ল আপনি কোনও প্রকার সতর্কতা ছাড়াই প্রেরণ পদ্ধতিকে ওভাররাইড করতে পারবেন এবং যখন আপনি ওভাররাইড করবেন__send__ তখন সেখানে একটি সতর্কতা বার্তা রয়েছে

সতর্কতা: নতুন সংজ্ঞা দেওয়া __send__ গুরুতর সমস্যা দেখা দিতে পারে

এটি কারণ বিরোধগুলি এড়াতে, বিশেষত রত্ন বা লাইব্রেরিতে যখন এটি ব্যবহৃত হবে এমন প্রসঙ্গটি অজানা, সর্বদা ব্যবহার করুন __send__ প্রেরণের পরিবর্তে করুন।

  1. প্রেরণ (বা __send__) এবং পাবলিক_সেন্ডের মধ্যে পার্থক্য হ'ল __send__কোনও বস্তুর ব্যক্তিগত পদ্ধতিগুলি প্রেরণ / কল করতে পারে এবং পাবলিক_সেন্ড করতে পারে না।
class Foo
   def __send__(*args, &block)
       "__send__"
   end
   def send(*args)
     "send"
   end
   def bar
       "bar"
   end
   private
   def private_bar
     "private_bar"
   end
end

Foo.new.bar #=> "bar"
Foo.new.private_bar #=> NoMethodError(private method 'private_bar' called for #Foo)

Foo.new.send(:bar) #=> "send"
Foo.new.__send__(:bar) #=> "__send__"
Foo.new.public_send(:bar) #=> "bar"

Foo.new.send(:private_bar) #=> "send"
Foo.new.__send__(:private_bar) #=> "__send__"
Foo.new.public_send(:private_bar) #=> NoMethodError(private method 'private_bar' called for #Foo)

শেষে __send__ বা প্রেরণ না করে ব্যক্তিগত পদ্ধতিতে সরাসরি কল এড়ানোর জন্য সর্বজনীন_সেন্ড ব্যবহার করার চেষ্টা করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.