سؤال

مجرد الحصول على رأسي حول برمجة روبي.دائمًا ما تنجح وحدات mixin/modules في إرباكي.

  • يشمل:يمزج في أساليب الوحدة المحددة كما طرق المثال في الفئة المستهدفة
  • يمتد:يمزج في أساليب الوحدة المحددة كما أساليب الطبقة في الفئة المستهدفة

فهل الفرق الرئيسي هو هذا فقط أم أن هناك تنينًا أكبر كامنًا؟على سبيل المثال

module ReusableModule
  def module_method
    puts "Module Method: Hi there!"
  end
end

class ClassThatIncludes
  include ReusableModule
end
class ClassThatExtends
  extend ReusableModule
end

puts "Include"
ClassThatIncludes.new.module_method       # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method            # "Module Method: Hi there!"
هل كانت مفيدة؟

المحلول

ما قلته هو الصحيح.ومع ذلك، هناك ما هو أكثر مما هو عليه.

إذا كان لديك فئة Klazz والوحدة النمطية Mod, ، مشتمل Mod في Klazz يعطي أمثلة Klazz الولوج إلى Modأساليب.أو يمكنك تمديد Klazz مع Mod إعطاء فصل Klazz الولوج إلى Modأساليب.ولكن يمكنك أيضًا تمديد كائن تعسفي به o.extend Mod.في هذه الحالة يحصل الكائن الفردي Modأساليب على الرغم من أن جميع الكائنات الأخرى لها نفس الفئة o لا.

نصائح أخرى

يمتد - يضيف أساليب وثوابت الوحدة المحددة إلى الفئة التعريفية للهدف (أي.فئة المفرد) على سبيل المثال

  • إذا اتصلت Klazz.extend(Mod), ، الآن لدى Klazz أساليب Mod (كطرق فئة)
  • إذا اتصلت obj.extend(Mod), ، الآن obj لديه أساليب Mod (كطرق مثيل)، ولكن لا يوجد مثيل آخر لـ obj.class تمت إضافة تلك الأساليب.
  • extend هي طريقة عامة

يشمل - بشكل افتراضي، يتم مزجه في أساليب الوحدة المحددة كطرق مثيل في الوحدة/الفئة المستهدفة.على سبيل المثال

  • إذا اتصلت class Klazz; include Mod; end;, ، الآن تتمتع جميع مثيلات Klazz بإمكانية الوصول إلى أساليب Mod (كطرق المثيل)
  • include هي طريقة خاصة، لأنها مصممة ليتم استدعاؤها من داخل فئة/وحدة الحاوية.

لكن, الوحدات في كثير من الأحيان تجاوز includeسلوك القرد عن طريق ترقيع القرد included طريقة.هذا بارز جدًا في كود Rails القديم. مزيد من التفاصيل من يهودا كاتز.

مزيد من التفاصيل حول include, ، بسلوكه الافتراضي، بافتراض أنك قمت بتشغيل التعليمات البرمجية التالية

class Klazz
  include Mod
end
  • إذا تم تضمين Mod بالفعل في Klazz، أو أحد أسلافه، فلن يكون لبيان التضمين أي تأثير
  • ويتضمن أيضًا ثوابت Mod في Klazz، طالما أنها لا تتعارض
  • فهو يمنح Klazz إمكانية الوصول إلى متغيرات وحدة Mod، على سبيل المثال. @@foo أو @@bar
  • يثير ArgumentError إذا كان هناك تضمينات دورية
  • إرفاق الوحدة باعتبارها السلف المباشر للمتصل (أي:فهو يضيف Mod إلى Klazz.ancestors، ولكن لا تتم إضافة Mod إلى سلسلة Klazz.superclass.superclass.superclass.لذلك، اتصل super في Klazz#foo سيتحقق من Mod#foo قبل التحقق من طريقة foo الخاصة بالطبقة الفائقة الحقيقية لـ Klazz.راجع RubySpec للحصول على التفاصيل.).

بالطبع، الوثائق الأساسية روبي هو دائمًا أفضل مكان للذهاب إليه لهذه الأشياء. مشروع روبيسبيك كان أيضًا مصدرًا رائعًا، لأنهم قاموا بتوثيق الوظيفة بدقة.

هذا صحيح.

خلف الكواليس، التضمين هو في الواقع اسم مستعار لـ append_features, ، والتي (من المستندات):

يتمثل تطبيق Ruby الافتراضي في إضافة الثوابت والأساليب ومتغيرات الوحدة النمطية لهذه الوحدة إلى Amodule إذا لم تتم إضافة هذه الوحدة بالفعل إلى Amodule أو أحد أسلافه.

جميع الإجابات الأخرى جيدة، بما في ذلك نصيحة البحث في RubySpecs:

https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb

https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb

أما بالنسبة لحالات الاستخدام:

اذا أنت يشمل الوحدة النمطية ReusableModule في فئة ClassThatIncludes، تتم الإشارة إلى الأساليب والثوابت والفئات والوحدات الفرعية والإعلانات الأخرى.

اذا أنت يمتد فئة ClassThatExtends مع الوحدة النمطية ReusableModule، ثم يتم الحصول على الأساليب والثوابت نسخ.من الواضح، إذا لم تكن حذرًا، يمكنك إضاعة الكثير من الذاكرة عن طريق تكرار التعريفات ديناميكيًا.

إذا كنت تستخدم ActiveSupport::Concern، فإن وظيفة .included() تتيح لك إعادة كتابة فئة التضمين مباشرة.تحصل الوحدة النمطية ClassMethods داخل القلق ممتد (منسوخ) في الفئة بما في ذلك.

وأود أيضًا أن أشرح الآلية أثناء عملها.إذا لم أكن على حق يرجى التصحيح.

عندما نستخدم include نحن نضيف رابطًا من فصلنا إلى وحدة تحتوي على بعض الأساليب.

class A
include MyMOd
end

a = A.new
a.some_method

لا تحتوي الكائنات على طرق، بل هناك فئات ووحدات نمطية فقط.اذن متى a يتلقى الرسالة some_method تبدأ طريقة البحث some_method في aفئة eigen، ثم في A فئة ومن ثم في مرتبطة ب A وحدات الفصل الدراسي إذا كان هناك بعض منها (بترتيب عكسي، يفوز آخر ما تم تضمينه).

عندما نستخدم extend نحن نضيف ارتباطًا بوحدة نمطية في فئة الكائن الذاتية.لذا، إذا استخدمنا A.new.extend(MyMod) فإننا نضيف رابطًا إلى وحدتنا إلى فئة eigen لمثيل A أو a' فصل.وإذا استخدمنا A.extend(MyMod) فإننا نضيف ارتباطًا إلى A(object's,classes هي أيضًا كائنات) eigenclass A'.

لذلك مسار البحث عن الأسلوب a على النحو التالي:a => a' => الوحدات المرتبطة بـ' class => A.

هناك أيضًا طريقة ملحقة تغير مسار البحث:

a => a' => الوحدات النمطية المسبقة إلى A => A => الوحدة النمطية المضمنة في A

اسف على سوء لغتي الانجليزية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top