سؤال

ما زلت جديدًا على روبي وأكتب أول برنامج صغير لي بعد الانتهاء من كتاب كوبر.لقد تم توجيهي إلى اتجاه تجنب ترقيع القرود ولكن المشكلة هي أنني لا أعرف ما هي البدائل لتحقيق نفس السلوك.في الأساس، أريد إضافة طريقة جديدة يمكن لكل كائن سلسلة الوصول إليها.الطريقة الواضحة لتصحيح القرود هي:

class String
  def do_magic
    ...magic...
  end
end

أذكر أن هناك طريقة لاستخدام String.send.لكن لا أستطيع أن أتذكر كيف تم ذلك ولا أين قرأته.هل يمكن لأي شخص أن يشير إلى أي بدائل تسمح لي بإتاحة هذه الطريقة لفئة السلسلة والكائنات الفرعية؟

هل كانت مفيدة؟

المحلول

وأي طريقة أخرى للقيام بذلك سيكون مجرد تركيب أكثر صعوبة لترميم قرد. هناك طرق تنطوي send وeval وجميع أنواع الأشياء، ولكن لماذا ؟ نمضي قدما ونفعل ذلك بالطريقة الواضحة.

وأنت تريد أن تكون حذرا من الترقيع قرد في المشاريع الكبيرة أو عندما يكون لديك التبعيات، لأنك يمكن أن تصل الرياح مع الصراعات عندما عدة اليدين والعبث في جميع أنحاء في نفس المكان. هذا لا يعني نظرة لبناء جملة بديل يحقق نفس الشيء - وهو ما يعني توخي الحذر عند اتخاذ التغييرات التي يمكن أن تؤثر على التعليمات البرمجية التي ليس لك. هذا ربما ليست مدعاة للقلق في حالة معينة. انها مجرد شيء قد تحتاج إلى معالجة في المشاريع الكبيرة.

وبديل واحد في روبي هو أنه يمكنك إضافة أساليب لكائن واحد.

a = "Hello"
b = "Goodbye"
class <<a
  def to_slang
    "yo"
  end
end
a.to_slang # => "yo"
b.to_slang # NoMethodError: undefined method `to_slang' for "Goodbye":String

نصائح أخرى

إذا كنت ترغب في إضافة طريقة جديدة يمكن الوصول إلى كل كائن سلسلة، ثم فعل ذلك بالطريقة لديك هو كيفية الحصول عليها القيام به.

وهناك ممارسة جيدة لوضع التمديدات الخاصة بك على الكائنات الأساسية في ملف منفصل (مثل string_ex.rb) أو دليل فرعي (مثل extensions أو core_ext). بهذه الطريقة، فمن الواضح ما تم تمديده، وأنه من السهل على أي شخص لمعرفة الكيفية التي تم تمديدها أو تغييرها.

وأين قرد الترقيع يمكن أن تذهب السيئة وعندما قمت بتغيير بعض السلوك الحالي للكائن الأساسية التي تسبب بعض التعليمات البرمجية الأخرى التي تتوقع وظيفة الأصلي إلى يسيئون التصرف.

ال object يحدد الفصل send, ، وجميع الكائنات ترث هذا.أنت "ترسل" كائنًا send طريقة.ال send معلمات الطريقة هي اسم الطريقة التي تريد استدعاءها كرمز، متبوعة بأي وسائط وكتلة اختيارية.تستطيع ايضا استخذام __send__.

>> "heya".send :reverse
=> "ayeh"

>> space = %w( moon star sun galaxy )
>> space.send(:collect) { |el| el.send :upcase! }
=> ["MOON", "STAR", "SUN", "GALAXY"]

يحرر..

ربما تريد استخدام define_method طريقة:

String.class_eval {
  define_method :hello do |name|
    self.gsub(/(\w+)/,'hello') + " #{name}"
  end
}

puts "Once upon a time".hello("Dylan")
# >> hello hello hello hello Dylan

وهذا يضيف أساليب المثيل.لإضافة أساليب الفصل:

eigenclass = class << String; self; end
eigenclass.class_eval {
  define_method :hello do
    "hello"
  end
}

puts String.hello
# >> hello

لا يمكنك تحديد الأساليب التي تتوقع كتلة بالرغم من ذلك.

قد يكون من الجيد أن نقرأه هذا الفصل من دليل لماذا مؤثر, ، يمكنك الانتقال إلى "Dwemthy’s Array" للوصول إلى عناصر البرمجة التعريفية.

وشكرا لكم أيها الرجال.

وجميع أعمال التنفيذ المقترحة. الأهم من ذلك، تعلمت أن تزن في الحال في اليد وتقرر ما إذا كان جوهر إعادة فتح (أو مكتبة) الطبقات هو فكرة جيدة أم لا.

وFWIW، وأشار صديق من تنفيذ send كنت أبحث عنه. لكن الآن بعد أن ألقي نظرة على ذلك، فإنه حتى أقرب إلى monkeypatching من جميع تطبيقات أخرى:)

module M
    def do_magic
    ....
    end
end
String.send(:include, M)

وكبديل لربط وظائف لفئات أو الكائنات، يمكنك دائما الذهاب المسار الوظيفي:

class StringMagic
  def self.do(string)
     ...
  end
end

StringMagic.do("I'm a String.") # => "I'm a MAGIC String!"

وو"التصحيح قرد" تصفون يمكن أن يكون في الواقع مشكلة إذا كان شخص آخر يريد أن تتطلب التعليمات البرمجية (كما في جوهره، على سبيل المثال). الذي هو القول انهم لا يريدون أيضا أن أضيف طريقة سلسلة يسمى do_magic؟ وأسلوب واحد الكتابة فوق الآخر، وهذا يمكن أن يكون تحديا التصحيح. إذا كان هناك أي فرصة والتعليمات البرمجية مفتوحة المصدر، فمن الأفضل إنشاء الفئة الخاصة بك:

class MyString < String
  def initialize(str)
    @str = str
  end
  def do_magic
    ...magic done on @str
    @str
  end
end

والآن، إذا كنت بحاجة إلى do_magic يمكنك

magic_str = MyString.new(str).do_magic
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top