تكنولوجيا

ما هو التغاير والتباين في البرمجة؟ – CloudSavvy IT

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

قبل تقديم أمثلة محددة ، يعتبر التباين مفهومًا مبهمًا على ما يبدو.دعونا نفكر في النوع الأساسي Animal نوع فرعي Dog.

interface Animal 
    public function walk() : void;

 
interface Dog extends Animal 
    public function bark() : void;

يمكن لجميع “الحيوانات” المشي ، ولكن “الكلاب” فقط يمكنها النباح. الآن ، دعونا نفكر في ما يحدث عندما نستخدم هذا التسلسل الهرمي للكائن في تطبيقنا.

قم بتوصيل الواجهة معًا

بسبب كل Animal يمكننا المشي ، يمكننا إنشاء واجهة عالمية لممارسة أي منها Animal.

interface AnimalController 
 
    public function exercise(Animal $Animal) : void;
 

هذه AnimalController عند exercise() طريقة سريعة Animal واجهه المستخدم.

interface DogRepository 
 
    public function getById(int $id) : Dog;
 

الآن لدينا ملف DogRepository الطرق المضمونة لإرجاع طريقة ما Dog.

إذا حاولنا مقارنة هذه القيمة بـ AnimalController؟

$AnimalController -> exercise($DogRepository -> getById(1));

في اللغات التي تدعم المعلمات المتغيرة ، هذا مسموح به. AnimalController يجب أن تحصل على واحدة Animal. ما نمرره هو في الواقع Dog, لكنها ما زالت مرضية Animal اتفافية.

هذه العلاقة مهمة بشكل خاص عند توسيع الفصول الدراسية.قد نريد عام AnimalRepository يمكنك البحث عن أي حيوان ليس لديه معلومات مفصلة عن أنواعه.

interface AnimalRepository 
 
    public function getById(int $id) : Animal;
 

 
interface DogRepository extends AnimalRepository 
 
    public function getById(int $id) : Dog;
 

DogRepository تعديل العقد AnimalRepository-لأن المتصل سيحصل على واحدة Dog بدلا من Animal-لكنه لم يغيره بشكل جذري. إنه يشرح فقط نوع الإرجاع بمزيد من التفصيل.نوع Dog مازال Animal. النوع هو متغير ، لذلك DogRepositoryتعريف مقبول.

انظر إلى العجز

دعونا ننظر الآن في المثال المعاكس.قد تحتاج واحدة DogController, لقد غير هذا الطريقة التي يمارس بها “الكلب”.منطقيا ، هذا لا يزال من الممكن تمديده AnimalController واجهه المستخدم.ومع ذلك ، في الواقع ، لا تسمح لك معظم اللغات بالتجاوز exercise() بالطريقة الضرورية.

interface AnimalController 
 
    public function exercise(Animal $Animal) : void;
 

 
interface DogController extends AnimalController 
 
    public function exercise(Dog $Dog) : void;
 

في هذا المثال DogController مكلف exercise() تقبل واحدة فقط Dog.هذا يتعارض مع تعريف المنبع AnimalController، السماح بمرور أي “حيوانات”. من أجل الوفاء بالعقد ، DogController لذلك ، أي Animal.

للوهلة الأولى ، يبدو هذا محيرًا وغير مفيد.عندما تستهدف AnimalController:

function exerciseAnimal(
    AnimalController $AnimalController,
    AnimalRepository $AnimalRepository,
    int $id) : void 
 
    $AnimalController -> exercise($AnimalRepository -> getById($id));

والقضية هي AnimalController ربما AnimalController أو أ DogController—طريقتنا لا تعرف تطبيق الواجهة الذي تستخدمه. هذا يرجع إلى نفس قواعد التغاير التي كانت متاحة سابقًا.

مثل AnimalController مايو اصبح ال DogController، يوجد الآن خطأ جسيم في وقت التشغيل ينتظر من يكتشفه. AnimalRepository يقوم دائمًا بإرجاع ملف Animal، لذلك ، إذا $AnimalController نعم نوع DogController، سوف يتعطل التطبيق.هذه Animal النوع غامض جدًا بحيث لا يمكن تمريره إليه DogController exercise() طريقة.

من الجدير بالذكر أن اللغات التي تدعم أسلوب التحميل الزائد ستقبل DogController.يسمح لك التحميل الزائد بتحديد طرق متعددة بنفس الاسم ، بشرط أن يكون لها أسماء مختلفة التوقيع (لديهم معلمات مختلفة و / أو أنواع إرجاع). DogController سيكون هناك اضافي exercise() تقبل فقط طريقة “الكلب”. ومع ذلك ، فإنه يحتاج أيضًا إلى تنفيذ التوقيعات الأولية التي تقبل أي “حيوانات”.

تعامل مع التناقضات

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

عند استخدام الأدوية العامة والمجموعات ، غالبًا ما تواجه مشكلات تباين.في هذه الحالات ، تريد عادةً AnimalCollection و أ DogCollection.ينبغي DogCollection تمديد AnimalCollection؟

هذه الواجهات هي كما يلي:

interface AnimalCollection 
    public function add(Animal $a) : void;
    public function getById(int $id) : Animal;

 
interface DogCollection extends AnimalCollection 
    public function add(Dog $d) : void;
    public function getById(int $id) : Dog;

النظرة الأولى getById()و Dog هو نوع فرعي من Animal. الأنواع متغايرة ، ويسمح بأنواع الإرجاع المتغيرة. هذا مقبول.نلاحظ مشكلة التباين مرة أخرى add() على الرغم من-DogCollection يجب أن يسمح بأي Animal لإرضاء AnimalCollection اتفافية.

عادة ، يمكن حل هذه المشكلة بشكل أفضل بجعل المجموعة غير قابلة للتغيير. السماح فقط بإضافة عناصر جديدة إلى مُنشئ المجموعة.ثم يمكنك القضاء add() في المجموع ، اصنع AnimalCollection مرشح فعال DogCollection يرث.

أشكال أخرى من الاختلاف

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

  • المتغيرات المزدوجة: إذا تم تطبيق التغاير واللوغاريتم على علاقة النوع في نفس الوقت ، يكون نظام الكتابة ثنائي المتغير. يستخدم TypeScript قبل TypeScript 2.6 التباين الثنائي كمعامل.
  • المتغيرات: إذا تم استخدام التباين المشترك أو التباين العكسي ، يكون النوع متغيرًا.
  • ثابت: لا توجد متغيرات من أي نوع.

عادة ، سوف تستخدم أنواعًا متغيرة أو متباينة. فيما يتعلق بميراث الفئة ، إذا كان النوع B والنوع A متغيرين ، تمديد A. إذا كان النوع B هو أحد أسلاف B ، فإنه والنوع A يكونان قابلين للتحويل.

ختاما

التباين هو مفهوم يشرح القيود داخل نظام النوع. بشكل عام ، ما عليك سوى تذكر أن التباين المشترك مقبول في نوع الإرجاع ، ويتم استخدام التباين المشترك للمعلمات.

قاعدة التباين مشتق من مبدأ استبدال Liskov. هذا يعني أنه يجب أن تكون قادرًا على استبدال مثيل لفئة بمثيل من صنفها الفرعي دون تغيير أي خصائص للنظام الأوسع.هذا يعني أنه إذا امتد النوع B إلى النوع A ، فعندئذٍ A يمكن استخدام الأمثلة التالية بدلاً من ذلك B.

استخدام المثال أعلاه يعني أننا يجب أن نكون قادرين على الاستبدال Animal مع Dog، أو AnimalController مع DogController.هنا نرى مرة أخرى لماذا DogController لا يمكن الكتابة exercise() فقط نقبل الكلاب – لن نتمكن من استبدالها بعد الآن AnimalController مع DogController، لأن المستهلكين مرت حاليا Animal الآن بحاجة إلى توفير ملف Dog بدلا من. التباين والتغاير يطبقان LSP ويضمنان معايير سلوك متسقة.

مقالات ذات صلة

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى