مقدمة للأنواع العامة في Java: التباين والتناقض

أنواع

Java هي لغة مكتوبة بشكل ثابت ، مما يعني أنه يجب عليك أولاً تعريف المتغير ونوعه قبل استخدامه.

فمثلا: int myInteger = 42;

أدخل الأنواع العامة.

أنواع عامة

التعريف: " النوع العام هو فئة عامة أو واجهة ذات معلمات على الأنواع."

تسمح لك الأنواع العامة بشكل أساسي بكتابة فئة (أو طريقة) عامة وعامة تعمل مع أنواع مختلفة ، مما يسمح بإعادة استخدام الكود.

بدلاً من تحديد objأن يكون من intنوع ، أو Stringنوع ، أو أي نوع آخر ، فإنك تحدد Boxالفئة لقبول معلمة نوع <؛ T>. بعد ذلك ، يمكنك nاستخدام حرف T لتمثيل هذا النوع العام في أي جزء داخل فصلك الدراسي.

الآن ، أدخل التغاير والتناقض.

التباين والتناقض

تعريف

يشير التباين إلى كيفية ارتباط التصنيف الفرعي بين الأنواع الأكثر تعقيدًا بالترتيب الفرعي بين مكوناتها (المصدر).

تعريف سهل التذكر (وغير رسمي للغاية) للتغاير والتناقض هو:

  • التباين المشترك: قبول الأنواع الفرعية
  • التباين: قبول الأنواع الفائقة

المصفوفات

في Java ، المصفوفات متغيرة ، والتي لها تأثيران.

أولاً ، T[]قد تحتوي مصفوفة من النوع على عناصر من النوع Tوأنواعه الفرعية.

Number[] nums = new Number[5];nums[0] = new Integer(1); // Oknums[1] = new Double(2.0); // Ok

ثانيًا ، المصفوفة من النوع S[]هي نوع فرعي من نوع T[]if Sهو نوع فرعي من T.

Integer[] intArr = new Integer[5];Number[] numArr = intArr; // Ok

ومع ذلك ، من المهم أن نتذكر أن: (1) numArrهو مرجع لنوع المرجع Number[]إلى "الكائن الفعلي" intArrمن "النوع الفعلي" Integer[].

لذلك ، سيتم تجميع السطر التالي بشكل جيد ، ولكنه سينتج وقت تشغيل ArrayStoreException(بسبب تلوث الكومة):

numArr[0] = 1.23; // Not ok

ينتج استثناء وقت التشغيل ، لأن Java تعرف في وقت التشغيل أن "الكائن الفعلي" intArrهو في الواقع مصفوفة من Integer.

علم الوراثة

مع الأنواع العامة ، ليس لدى Java أي وسيلة لمعرفة وقت التشغيل لمعلومات النوع لمعلمات النوع ، بسبب محو النوع. لذلك ، لا يمكن أن تحمي من التلوث في وقت التشغيل.

على هذا النحو ، فإن الأدوية الجنيسة ثابتة.

ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Not okArrayList anotherIntArrList = intArrList; // Ok

يجب أن تتطابق معلمات النوع تمامًا ، للحماية من تلوث الكومة.

لكن أدخل أحرف البدل.

أحرف البدل والتغاير والتباين

باستخدام أحرف البدل ، من الممكن أن تدعم الأدوية الجنيسة التغاير والتباين.

التغيير والتبديل في المثال السابق ، نحصل على هذا ، والذي يعمل!

ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Ok

علامة الاستفهام "؟" يشير إلى حرف بدل يمثل نوعًا غير معروف. يمكن أن يكون الحد الأدنى ، مما يقيد النوع المجهول ليكون نوعًا معينًا أو نوعًا فائقًا.

لذلك ، في السطر 2 ، ? super Integerيُترجم إلى "أي نوع من النوع الصحيح أو نوعه الفائق".

يمكنك أيضًا تحديد الحد الأعلى لحرف البدل ، والذي يقيد النوع غير المعروف ليكون نوعًا معينًا أو نوعًا فرعيًا ، باستخدام ? extends Integer.

للقراءة فقط والكتابة فقط

ينتج عن التباين والتناقض بعض النتائج المثيرة للاهتمام. أنواع المتغيرات المشتركة للقراءة فقط ، بينما الأنواع المتباينة هي للكتابة فقط.

تذكر أن الأنواع المتغايرة تقبل الأنواع الفرعية ، لذلك ArrayList er> can contain any object that is either of a Number type or its subtype.

In this example, line 9 works, because we can be certain that whatever we get from the ArrayList can be upcasted to a Number type (because if it extends Number, by definition, it is a Number).

But nums.add() doesn’t work, because we cannot be sure of the “actual type” of the object. All we know is that it must be a Number or its subtypes (e.g. Integer, Double, Long, etc.).

With contravariance, the converse is true.

Line 9 works, because we can be certain that whatever the “actual type” of the object is, it must be Integer or its supertype, and thus accept an Integer object.

But line 10 doesn’t work, because we cannot be sure that we will get an Integer. For instance, nums could be referencing an ArrayList of Objects.

Applications

Therefore, since covariant types are read-only and contravariant types are write-only (loosely speaking), we can derive the following rule of thumb: “Producer extends, consumer super”.

A producer-like object that produces objects of type T can be of type parameter T>, while a consumer-like object that consumes objects oftype T can be of type parameter super T>.