كيف يقارن تباين موقع الاستخدام من Java مع تباين موقع C#؟

StackOverflow https://stackoverflow.com/questions/4231305

  •  26-09-2019
  •  | 
  •  

سؤال

فهمي هو أن تحديد التباين للأشكال في C# يحدث على مستوى إعلان النوع: عندما تقوم بإنشاء نوع عام ، يمكنك تحديد التباين في وسيطات النوع. في Java ، من ناحية أخرى ، يتم تحديد التباين حيث يتم استخدام عام: عند إنشاء متغير من نوع عام ، يمكنك تحديد كيفية تختلف وسيطات نوعها.

ما هي إيجابيات وسلبيات لكل خيار؟

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

المحلول

سأجيب فقط على الاختلافات بين موقع الإعلان وتباين موقع الاستخدام ، لأنه ، في حين أن C# و Java Generics تختلف بعدة طرق أخرى ، فإن تلك الاختلافات في الغالب متعامد مع التباين.

أولاً ، إذا كنت أتذكر أن التباين في الموقع بشكل صحيح يكون أقوى بشكل صارم من تباين موقع الإعلان (على الرغم من تكلفة التوصل) ، أو على الأقل تحرفات Java (والتي هي في الواقع أقوى من تباين موقع الاستخدام). هذه القوة المتزايدة مفيدة بشكل خاص لللغات التي يتم فيها استخدام التركيبات الحكومية بشكل كبير ، مثل C# و Java (ولكن Scala أقل بكثير ، خاصة وأن قوائمها القياسية غير قابلة للتغيير). انصح List<E> (أو IList<E>). نظرًا لأنه يحتوي على أساليب لإضافة E -'s والحصول على E's ، فهي ثابتة فيما يتعلق بـ E ، وبالتالي لا يمكن استخدام تباين موقع الإعلان. ومع ذلك ، مع تباين موقع الاستخدام يمكنك فقط أن تقول List<+Number> للحصول على مجموعة فرعية متغيرة List و List<-Number> للحصول على مجموعة فرعية متجانسة من List. في لغة موقع الإعلان ، سيتعين على مصمم المكتبة إنشاء واجهات منفصلة (أو فئات إذا سمحت براالة متعددة من الفئات) لكل مجموعة فرعية ولديها List تمديد تلك الواجهات. إذا لم يفعل مصمم المكتبة هذا (لاحظ أن C#S IEnumerable فقط لمجموعة فرعية صغيرة من الجزء المتغير من IList) ، إذن أنت محظوظ وعليك أن تلجأ إلى نفس المتاعب التي يتعين عليك القيام بها بلغة دون أي نوع من التباين.

هذه هي مزايا ميراث موقع الاستخدام على ميراث موقع الإعلان. إن ميزة الميراث في موقع الإعلان على ميراث موقع الاستخدام هي بشكل أساسي تصحيح للمستخدم (شريطة أن يمر المصمم بجهود فصل كل فئة/واجهة إلى أجزاء متغيرة ومتناقضة). لشيء مثل IEnumerable أو Iterator, ، من الجيد ألا تضطر إلى تحديد التباين في كل مرة تستخدم فيها الواجهة. جعلت Java هذا مزعجًا بشكل خاص باستخدام بناء جملة مطول (باستثناء الاستعادة الحيوية التي يكون حل Java مثاليًا بشكل أساسي).

بالطبع ، يمكن أن تتعايش هذه الميزات اللغتين. بالنسبة لمعلمات النوع التي تتغير بشكل طبيعي أو متجانسة (مثل في IEnumerable/Iterator) ، أعلن ذلك في الإعلان. بالنسبة لمعلمات النوع التي تكون ثابتة بشكل طبيعي (كما في (I)List) ، أعلن عن نوع التباين الذي تريده في كل مرة تستخدم فيها. فقط لا تحدد تباين موقع الاستخدام للوسائط مع تباين في موقع الإعلان لأن ذلك يجعل الأمور مربكة.

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

نصائح أخرى

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

لكن ضع في اعتبارك ، أن Java أو C# هي أمثلة على تصميم اللغة الجيدة.

في حين جافا حصلت على التباين بشكل صحيح والعمل بشكل مستقل عن JVM بسبب التحسينات المتوافقة VM في Java 5 و Type-erasure ، والتباين في موقع الاستخدام يجعل الاستخدام مرهقًا بعض الشيء ، وقد جذب التنفيذ الخاص للنوع الإيراسي النقد الذي تم تسليمه جيدًا.

ج#يأخذ نموذج التباين في موقع الإعلان العبء بعيدًا عن مستخدم المكتبة ، ولكن أثناء تقديمها للمواد العامة المُعاد ، قاموا ببناء قواعد التباين بشكل أساسي في VM الخاصة بهم. حتى اليوم ، لا يمكنهم دعمهم بالكامل/المخالفات بسبب هذا الخطأ (والمقدمة غير المتوافقة مع غير المتوافقة مع فصول التجميع Reified قامت بتقسيم المبرمجين إلى معسكرين).

هذا يشكل تقييدًا صعبًا على جميع اللغات التي تستهدف CLR وهو أحد الأسباب التي تجعل لغات البرمجة البديلة أكثر حيوية على JVM على الرغم من أنه يبدو أن CLR لديه "ميزات أجمل كثيرًا".

دعنا ننظر إلى سكالا: Scala عبارة عن مختلط وظيفي موجه بشكل كامل ، يعمل على JVM. إنهم يستخدمون محو النوع مثل Java ، ولكن من الأسهل فهم تنفيذ الأدوية الجيرية وتباين (موقع الإعلان) ، وأكثر وضوحًا وأكثر قوة من Java (أو C#'، لأن VM لا يفرض قواعد حول كيفية التباين الشغل. يتحقق برنامج التحويل البرمجي Scala من تدوين التباين ويمكنه رفض رمز المصدر غير السليم في وقت الترجمة بدلاً من رمي الاستثناءات في وقت التشغيل ، في حين يمكن استخدام ملفات .class الناتجة بسلاسة من Java.

أحد عيب تباين موقع الإعلان هو أنه يبدو أنه يجعل الاستدلال نوعًا أكثر صعوبة في بعض الحالات.

في الوقت نفسه ، يمكن لـ Scala استخدام الأنواع البدائية دون ملاكمةها في مجموعات مثل C# باستخدام @specialized التعليق التوضيحي الذي يخبر برنامج التحويل البرمجي Scala بإنشاء تطبيق واحد أو عدة تطبيقات إضافية لفئة أو طريقة متخصصة في النوع البدائي المطلوب.

يمكن لـ Scala أيضًا "تقريبًا" الأدوية الجيرية باستخدام البيان التي تسمح لهم باسترداد الأنواع العامة في وقت التشغيل كما في C#.

عيوب الأدوية الجيرية جافا

إحدى النتائج هي أن إصدار Java يعمل فقط مع أنواع المراجع (أو أنواع القيمة المعبأة) وليس من نوع القيمة. IMO هذا هو أكبر عيب لأنه يمنع الأداء العالي الأداء في الكثير من السيناريوهات ويتطلب الكتابة اليدوية لأنواع متخصصة.

لا يضمن ذلك ثابتًا مثل "هذه القائمة تحتوي فقط على كائنات من النوع X" وتحتاج إلى شيكات وقت التشغيل في كل getter. النوع العام موجود حقا.

عند استخدام الانعكاس ، لا يمكنك طرح مثيل لكائن عام يعاني من معلمات عامة.

مزايا الأدوية الأدوية الجازية

يمكنك الحصول على التباين/يمكن أن يلقي بين معلمات عامة مختلفة.

Java: Generics Variance Generics منذ Java 5. صفيفات متغيرة معطلة مع بناء جملة مختلف منذ 1.0. لا توجد معلومات نوع وقت التشغيل من الأدوية الجيرية.

C#: استخدام الأعياد التباين في الموقع منذ C# 2.0. إضافة تباين موقع الإعلان في C# 4.0. صفيفات متغيرة مكسورة مع بناء جملة مختلف منذ 1.0 (مشكلة متطابقة لجافا). الأوليات "Reified" تعني أن معلومات النوع لم تضيع في وقت التجميع.

Scala: كل من تباين موقع الاستخدام/الإعلان منذ الإصدارات المبكرة من اللغة (على الأقل منذ عام 2008). لا تعد المصفوفات ميزة لغة منفصلة ، لذلك يمكنك استخدام نفس جملة Syntax و Type Type Variance. يتم تنفيذ بعض المجموعات على مستوى VM مع صفائف JVM بحيث تحصل على أداء متساوٍ أو أفضل في وقت التشغيل مقارنة برمز Java.

لتوضيح مشكلة السلامة في نوع مجموعة C#/Java: يمكنك إلقاء كلب [] على حيوان أليف [] وإضافة قطة وتشغيل خطأ في وقت التشغيل لم يتم اكتشافه في وقت التجميع. نفذت Scala هذا بشكل صحيح.

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