هل المندوبون ليسوا واجهات اختزال فقط؟

لنفترض أن لدينا:

interface Foo 
{
 bool Func(int x);
}

class Bar: Foo
{
  bool Func(int x)
  {
   return (x>0);
  }  
}

class Baz: Foo
{
  bool Func(int x)
  {
   return (x<0);
  }  
}

الآن يمكننا إلقاء القبض على شريط حول وباز باعتباره فوس واستدعاء أساليب Func بهم.

يقوم المندوبون بتبسيط ذلك قليلاً:

delegate bool Foo(int x);

bool Bar(int x)
{
 return (x<0);
}

bool Baz(int x)
{
 return (x>0);
}

الآن يمكننا إلقاء القبض على بار وباز كمندوبين فو.

ما هي الفائدة الحقيقية للمندوبين ، باستثناء الحصول على رمز أقصر؟

0
وأضاف تحرير
الآراء: 8

10 إجابة

لا ، المفوضون لمؤشرات الطريقة. ثم يمكنك التأكد من صحة توقيع الأسلوب المقترن مع المفوض.

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

Take a look at the List<> class with the Find method. Now you get to define what determines if something is a match or not, without requiring items contained in the class to implement IListFindable or something similar.

0
وأضاف

المفوض هو مؤشر أسلوب مكتوب. هذا يمنحك مرونة أكثر من واجهات لأنه يمكنك الاستفادة من التغاير و contravariance ، ويمكنك تعديل حالة الكائن (عليك تمرير هذا المؤشر مع funators يستند إلى الواجهة).

أيضا ، المندوبين لديهم الكثير من السكر النحوي الجميل الذي يسمح لك أن تفعل أشياء مثل الجمع بينها بسهولة.

0
وأضاف

في اقتراح واحد على الأقل لإضافة عمليات الإغلاق (أي المفوضين المجهولين) إلى Java ، فإنها تعادل الواجهات بأسلوب عضو واحد.

0
وأضاف

يمكن للمرء أن يفكر في المندوبين كواجهة تفاعلية لطريقة تعرف ما هي الحجج والعودة التي يجب أن تكون عليها طريقة ما لتلائم المندوب.

0
وأضاف

يشارك المفوض الكثير من النقاط المشتركة مع مرجع واجهة يحتوي على طريقة واحدة من وجهة نظر المتصل.

في المثال الأول ، يعتبر Baz and Bar من الفصول الدراسية ، والتي يمكن أن تكون موروثة ومحفوظة. في المثال الثاني ، Baz and Bar هما طريقتان.

لا يمكنك تطبيق مراجع الواجهة على أي فئة تطابق عقد الواجهة. يجب أن تعلن الفئة صراحة أنها تدعم الواجهة. يمكنك تطبيق مرجع مفوض لأي طريقة تطابق التوقيع.

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

0
وأضاف

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

0
وأضاف

نعم ، يمكن اعتبار المفوض كواجهة مع طريقة واحدة.

0
وأضاف

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

كما أن التعليمات البرمجية القصيرة والموجزة أكثر فائدة أيضًا.

0
وأضاف
انها ليست مجرد متغيرات الأعضاء. إنه حتى متغيرات أو معلمات محلية للطريقة يتم تعريف مندوب مجهول داخل.
وأضاف المؤلف Daniel Earwicker, مصدر
supercat صحيح. لكن لماذا تعتقد أن واجهات العمل "ستعمل بشكل أفضل" من المندوبين؟ المفوض منطقيًا نفس الشيء مثل واجهة أسلوب مفرد.
وأضاف المؤلف Daniel Earwicker, مصدر
(1) "حالات الكومة" ليست مكلفة خاصة في CLR. انظر smellegantcode.wordpress. كوم/2009/03/01/و hellip؛ (2) ما هو الخطأ في <�كود> تفويض الفراغ MyDelegate (T الخامس) حيث T: IFoo، إيبار؛ </​​القانون>؟
وأضاف المؤلف Daniel Earwicker, مصدر
وأضاف المؤلف Daniel Earwicker, مصدر
DanielEarwicker: يحدد الروتين الذي يتم تعريف الإغلاق فيه طبقة خاصة "مخفية" لاحتواء المتغيرات المحلية ، ويخلق مثيلًا لمثل هذه الفئة في أي وقت تدخل فيه هذه المتغيرات نطاقًا ، ويستخدم حقول تلك الفئة بدلاً من المجال "الطبيعي" المحلي. المتغيرات. سيناريوهات تستخدم الإغلاق تعمل بشكل أفضل مع واجهات أكثر من المفوضين.
وأضاف المؤلف supercat, مصدر
DanielEarwicker: على الأقل سببين: (1) لنفترض أن أحد الروتين سيتصل بـ Action في بعض الحالات ، وفي هذه الحالة أريد أن أتصل بـ Foo (x) مع القيمة الحالية للمتغير المحلي x . يتطلب تمرير مثل هذا الطلب كمفوض إنشاء اثنين من حالات الكومة: كائن فئة مؤقت لعقد x ، ومفوض لاستدعاءه. سيتطلب تمرير الطلب كنوع واجهة إنشاء نسخة كومة واحدة (تنفيذ الواجهة). قد لا يتطلب اجتيازه كصفة عامة مقيدة بالواجهة إنشاء أي منها.
وأضاف المؤلف supercat, مصدر
(2) يمكن أن تحتوي الواجهات على طرق عامة مفتوحة ، بينما لا يستطيع المندوبون ذلك. لنفترض أن لدي مجموعة من الكائنات ليس لها نوع أساسي مشترك ، ولكن جميعها من أنواع مقيدة لتطبيق IFoo و IBar. أود أن أكون قادرة على تشغيل روتين موفر من الخارج والذي يأخذ معلمة مقيدة إلى IFoo و IBar. لا توجد طريقة لتحديد أن المفوض يأخذ معلمة من النوع T: IFoo ، IBar ولكن من الممكن أن تعلن طريقة واجهة يفعل ذلك.
وأضاف المؤلف supercat, مصدر
DanielEarwicker: المشكلة في ذلك هي أن الروتين الذي يقوم بإنشاء المفوض عليه تحديد نوع T . لنفترض أن الفئة تحتوي على مجموعة من الكائنات التي تعمل جميعها على تنفيذ I1 و I2 ، ولكنها لا تحتوي على نوع أساسي مشترك يقوم بتنفيذ كلاهما ؛ تود أن تكشف طريقة ForAll . إذا قبلت هذه الطريقة كائنًا من نوع واجهة IActUponConstrained {void Act (T param) حيث T: I1 و I2؛} ، يمكن أن تستدعي Act < T> على كل عنصر دون الكيان الذي أنشأ IActUponConstrained مضطراً إلى معرفة أنواع العناصر الفردية.
وأضاف المؤلف supercat, مصدر
DanielEarwicker: إذا لم يرغب المرء في استخدام الانعكاس ، فإن الواجهة العامة ضرورية لأن معلمات الكتابة العامة يمكنها فقط تحريك "أسفل" (أعمق إلى) مكدس الاستدعاءات. قد تحتوي مجموعة من فئة abstract ThingImplementing على مثيلات الفئات المشتقة ThingImplementing .WithType حيث ActualType: I1، I2 . يرتبط كل مثيل بالنوع العام الذي تم إنشاؤه به ، ولكن إذا كان سيتم استدعاء رمز آخر باستخدام معلمة النوع هذه ، فسيتعين على المثيل إجراء المكالمة نفسها. إذا كانت Foo و Bar غير ذات صلة ولكن تم تنفيذها ...
وأضاف المؤلف supercat, مصدر
... كلا الواجهات ، لا توجد طريقة لتعريف مفوض بمعلمة نوع مقيدة بكل من I1 و I2 ، والتي ThingImplementing يمكن لـ .WithType تمرير Foo ، وإلى ThingImplementing .WithType يمكن أن يمرر شريط </القانون>. ومع ذلك ، يمكن للمرء تحديد تطبيق IActUponConstrained ، وتمريره لكلا الكائنين ، ولديه أول مكالمة Act (Foo param) بينما المكالمة الثانية Act (Bar param) .
وأضاف المؤلف supercat, مصدر
تضمين التغريدة ردًا علىDanielEarwicker القدرة على الحصول على مستهلك نوع واجهة توفر معلمة نوع عامة لا يشبه أي شيء يمكن القيام به مع مفوضين. في الواقع ، لست متأكدًا من أن هناك حاجة حقيقية للمندوبين في الإطار إذا كان بمقدور المجمعين القيام بواجهات عامة بعض الأشياء التي يفعلونها للمندوبين (على سبيل المثال ، إعطاء واجهة باستخدام Invoke طريقة وجود توقيع معين ، بناء فئة الذي يأخذ منشئين اثنين من التطبيقات من تلك الواجهة ، والتي تنفذ استدعاء عن طريق استدعاء كلتا الحالتين). بالتاكيد...
وأضاف المؤلف supercat, مصدر
... لم تتواجد الأدوية الجنيسة في .net 1.0 ، لذا كان المندوبون شبه العامون مؤقتًا ضروريًا. بالمناسبة ، أتساءل لماذا لا تقوم المشتقات التي تم إنشاؤها من خلال Delegate بتحديد الكلمات الخاصة بهم Combine و Remove ؟ يمكن أن تعمل مثل هذه الطرق بشكل صحيح مع أنواع المندلات غير المنتظمة ، بينما لا يمكن لـ Delegate.Combine .
وأضاف المؤلف supercat, مصدر
من المثير للاهتمام ملاحظة أن المندوبين يمكنهم الوصول إلى الأعضاء. يمكن أن تكون طريقة اللف المغلفة للطبقة بمثابة ساعي للبيانات الناتجة ولكن الوصول المباشر هو طريقة أسرع بكثير للقيام بذلك.
وأضاف المؤلف Rick Minerich, مصدر

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

كما يمكن استخدامها أيضًا بنفس الطريقة: فبدلاً من اجتياز فصل بأكمله يحتوي على الطريقة التي تحتاجها ، يمكنك تمريرها في مندوب واحد فقط. هذا يحفظ مجموعة كاملة من التعليمات البرمجية ويخلق رمز أكثر قابلية للقراءة.

علاوة على ذلك ، مع ظهور تعبيرات لامدا يمكن الآن تعريفها بسهولة على الطاير وهي مكافأة ضخمة. في حين أنه من الممكن بناء فصول على الطاير في C# ، فإنه حقا ألم ضخم في المؤخرة.

المقارنة بين الاثنين هو مفهوم مثير للاهتمام. لم أكن قد سبق أن نظرت إلى مدى تشابه الأفكار من حالة استخدام ورؤية هيكلة الشفرة.

0
وأضاف

إن الواجهات والمندوبين هما شيئان مختلفان تمامًا ، على الرغم من أنني أفهم إغراء وصف المندوبين في مصطلحات شبيهة بالواجهة لتسهيل الفهم ... لكن عدم معرفة الحقيقة قد يؤدي إلى الارتباك أسفل الخط.

تم إلهام المندوبين (جزئيا) بسبب الفن الأسود لمؤشرات أسلوب C ++ غير كافية لأغراض معينة. مثال تقليدي هو تطبيق آلية تمرير الرسائل أو التعامل مع الأحداث. يسمح لك المندوبون بتعريف توقيع طريقة بدون أي معرفة بأنواع أو واجهات فئة - يمكنني تحديد "void eventHandler (الحدث * e)" المفوض واستدعائه على أي فئة تقوم بتطبيقه.

للتعرف على بعض هذه المشكلة الكلاسيكية ، ولماذا يفضل المندوبون قراءة هذا و ثم هذا .

0
وأضاف