الأدوية الجيرية: قائمة <؟ يمتد الحيوان> هو نفس القائمة ؟
-
24-09-2019 - |
سؤال
أنا فقط أحاول فهم extends
الكلمة الرئيسية في جافا جينك.
List<? extends Animal>
يعني أننا نستطيع أن نحسم أي كائن في List
أيّ هو Animal
ثم لن يعني ما يلي أيضًا نفس الشيء:
List<Animal>
هل يمكن لأي شخص مساعدتي في معرفة الفرق بين الاثنين أعلاه؟ إلي extends
فقط يبدو زائدة عن الحاجة هنا.
شكرًا!
المحلول
List<Dog>
هو نوع فرعي من List<? extends Animal>
, ، ولكن ليس نوعا فرعي من List<Animal>
.
لماذا List<Dog>
ليس نوعًا فرعيًا من List<Animal>
؟ النظر في المثال التالي:
void mySub(List<Animal> myList) {
myList.add(new Cat());
}
إذا سمح لك بتمرير أ List<Dog>
إلى هذه الوظيفة ، ستحصل على خطأ في وقت التشغيل.
تحرير: الآن ، إذا استخدمنا List<? extends Animal>
بدلاً من ذلك ، سيحدث ما يلي:
void mySub(List<? extends Animal> myList) {
myList.add(new Cat()); // compile error here
Animal a = myList.get(0); // works fine
}
أنت يستطع تمرير أ List<Dog>
إلى هذه الوظيفة ، لكن المترجم يدرك أن إضافة شيء إلى القائمة قد يجعلك في مشكلة. إذا كنت تستخدم super
بدلاً من extends
(يسمح لك بتمرير أ List<LifeForm>
)، على العكس.
void mySub(List<? super Animal> myList) {
myList.add(new Cat()); // works fine
Animal a = myList.get(0); // compile error here, since the list entry could be a Plant
}
النظرية وراء هذا مشارك ومخالفة.
نصائح أخرى
أرى أنك قبلت بالفعل إجابة ، لكنني أود فقط إضافة رأيي ، حيث أعتقد أنني يمكن أن أكون ببعض المساعدة هنا.
الفرق بين List<Animal>
و List<? extends Animal>
كالتالي.
مع List<Animal>
, ، أنت تعرف ما لديك هو بالتأكيد قائمة بالحيوانات. ليس من الضروري أن يكونوا جميعًا في الواقع "حيوانًا - يمكن أيضًا أن يكونوا مستمقين. على سبيل المثال ، إذا كان لديك قائمة بالحيوانات ، فمن المنطقي أن الزوجين يمكن أن يكونا ماعزًا ، وبعضهما القطط ، إلخ - أليس كذلك؟
على سبيل المثال ، هذا صحيح تمامًا:
List<Animal> aL= new List<Animal>();
aL.add(new Goat());
aL.add(new Cat());
Animal a = aL.peek();
a.walk(); // assuming walk is a method within Animal
بالطبع ، ما يلي ليس تكون صالحة:
aL.peek().meow(); // we can't do this, as it's not guaranteed that aL.peek() will be a Cat
مع List<? extends Animal>
, ، أنت تدلي ببيان حول نوع القائمة أنت تتعامل مع.
علي سبيل المثال:
List<? extends Animal> L;
هذا في الواقع ليس يمكن إعلان نوع الكائن l كبح. إنه بيان حول أنواع القوائم التي يمكن أن تشير إليها.
على سبيل المثال ، يمكننا القيام بذلك:
L = aL; // remember aL is a List of Animals
ولكن الآن كل المترجم يعرف عن L هو أنه قائمة [إما حيوان أو نوع فرعي للحيوان
حتى الآن ما يلي غير صالح:
L.add(new Animal()); // throws a compiletime error
لأنه على كل ما نعرفه ، يمكن أن يشير L إلى قائمة من الماعز - والتي لا يمكننا إضافة حيوان.
هنا لماذا:
List<Goat> gL = new List<Goat>(); // fine
gL.add(new Goat()); // fine
gL.add(new Animal()); // compiletime error
في ما سبق ، نحاول إلقاء حيوان كماعز. هذا لا يعمل ، لأنه إذا حاولنا بعد القيام بذلك أن نجعل هذا الحيوان يقوم "برأس" ، مثل الماعز؟ لا نعرف بالضرورة أن الحيوان يمكنه فعل ذلك.
ليس. List<Animal>
يقول أن القيمة المخصصة لهذا المتغير يجب أن تكون من "النوع" List<Animal>
. هذا لا يعني أنه يجب أن يكون هناك فقط Animal
الكائنات ، يمكن أن يكون هناك فئات فرعية أيضا.
List<Number> l = new ArrayList<Number>();
l.add(4); // autoboxing to Integer
l.add(6.7); // autoboxing to Double
يمكنك استخدام List<? extends Number>
بناء إذا كنت مصلحة في القائمة التي حصلت عليها Number
الكائنات ، لكن كائن القائمة نفسه لا يحتاج إلى أن يكون من النوع List<Number>
ولكن هل يمكن لأي قائمة أخرى من الفئات الفرعية (مثل List<Integer>
).
هذا هو الاستخدام في وقت ما لوسيطات الطريقة التي يمكن أن تقولها "أريد قائمة من Numbers
, ، لكنني لا أهتم إذا كان الأمر مجرد List<Number>
, ، يمكن أن يكون List<Double>
جدا". هذا يتجنب بعض القوالب الغريبة إذا كان لديك قائمة ببعض الفئات الفرعية ، لكن الطريقة تتوقع قائمة من الأساس.
public void doSomethingWith(List<Number> l) {
...
}
List<Double> d = new ArrayList<Double>();
doSomethingWith(d); // not working
هذا لا يعمل كما تتوقع List<Number>
, ، ليس أ List<Double>
. ولكن إذا كتبت List<? extends Number>
يمكنك تمرير List<Double>
الأشياء حتى لا تكون كذلك List<Number>
أشياء.
public void doSomethingWith(List<? extends Number> l) {
...
}
List<Double> d = new ArrayList<Double>();
doSomethingWith(d); // works
ملحوظة: هذه الأشياء بأكملها لا علاقة لها براالة الكائنات في القائمة نفسها. لا يزال بإمكانك إضافة Double
و Integer
الأشياء في أ List<Number>
قائمة ، مع أو بدون ? extends
أمور.