سؤال

أولاً، أفهم الأسباب التي تجعل الواجهة أو الفئة المجردة (في مصطلحات .NET/C#) لا يمكن أن تحتوي على طرق ثابتة مجردة.سؤالي يركز أكثر على أفضل حل للتصميم.

ما أريده هو مجموعة من الفئات "المساعدة" التي تحتوي جميعها على أساليب ثابتة خاصة بها، بحيث إذا حصلت على كائنات A وB وC من بائع طرف ثالث، فيمكنني الحصول على فئات مساعدة بأساليب مثل

AHelper.RetrieveByID(string id);
AHelper.RetrieveByName(string name);
AHelper.DumpToDatabase();

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

يمكنني دائمًا جعل هذه الأساليب غير ثابتة ثم إنشاء مثيل للكائنات أولاً مثل

AHelper a = new AHelper();
a.DumpToDatabase();

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

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

المحلول

انظر الى ردك وأنا أفكر على السطور التالية:

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

أفضّل الخيار الثاني، رغم أنه يعود إليك بالطبع.إذا كنت تريد مني الخوض في مزيد من التفاصيل، فيرجى إبلاغي بذلك وسأكون سعيدًا بالتعديل/التحديث :)

نصائح أخرى

لو كنت أنت سأحاول تجنب أي احصائيات.IMHO لقد انتهى بي الأمر دائمًا بنوع من مشكلات المزامنة مع الإحصائيات.ومع ذلك، فأنت تقدم مثالًا كلاسيكيًا للبرمجة العامة باستخدام القوالب.سأعتمد الحل القائم على القالب الخاص بـ Rob Copper المقدم في إحدى المشاركات أعلاه.

للحصول على حل عام لمثالك، يمكنك القيام بذلك:

public static T RetrieveByID<T>(string ID)
{
     var fieldNames = getFieldNamesBasedOnType(typeof(T));
     QueryResult qr = webservice.query("SELECT "+fieldNames + " FROM "
                                     + tyepof(T).Name
                                     +" WHERE Id = '" + ID + "'");
     return (T) qr.records[0];
}

أنا شخصياً ربما أتساءل لماذا يحتاج كل نوع إلى طريقة ثابتة قبل التفكير أكثر.

لماذا لا تنشئ فئة أدوات مساعدة بالطرق الثابتة التي يحتاجون إلى مشاركتها؟(على سبيل المثال ClassHelper.RetrieveByID(string id) أو ClassHelper<ClassA>.RetrieveByID(string id)

في تجربتي مع هذا النوع من "الحواجز"، فإن المشكلة ليست في القيود المفروضة على اللغة، ولكن في القيود المفروضة على تصميمي..

كيف يتم الارتباط بين ObjectA وAHelper؟يكون AHelper.RetrieveByID() نفس المنطق كما BHelper.RetrieveByID()

إذا كانت الإجابة بنعم، فماذا عن النهج القائم على فئة الأداة المساعدة (فئة ذات أساليب ثابتة عامة فقط ولا توجد حالة)

static [return type] Helper.RetrieveByID(ObjectX x) 

لا يمكنك زيادة التحميل على الأساليب من خلال تغيير نوع الإرجاع فقط.

يمكنك استخدام أسماء مختلفة:

static AObject GetAObject(string id);
static BObject GetBObject(string id);

أو يمكنك إنشاء فصل دراسي مع مشغلي الصب:

class AOrBObject
{ 
   string id;
   AOrBObject(string id) {this.id = id;}

   static public AOrBObject RetrieveByID(string id)
   {
        return new AOrBObject(id);
   }

   public static AObject explicit operator(AOrBObject ab) 
    { 
        return AObjectQuery(ab.id);
    }

   public static BObject explicit operator(AOrBObject ab)
    { 
        return BObjectQuery(ab.id);
    } 
}

ثم يمكنك تسميتها هكذا:

 var a = (AObject) AOrBObject.RetrieveByID(5);
 var b = (BObject) AOrBObject.RetrieveByID(5); 

في C# 3.0، يمكن استخدام الأساليب الثابتة على الواجهات كما لو كانت جزءًا منها باستخدام أساليب الامتداد، كما هو الحال مع DumpToDatabase() أدناه:

static class HelperMethods
 {  //IHelper h = new HeleperA();
    //h.DumpToDatabase() 
    public static void DumpToDatabase(this IHelper helper) { /* ... */ }

    //IHelper h = a.RetrieveByID(5)
    public static IHelper RetrieveByID(this ObjectA a, int id) 
     { 
          return new HelperA(a.GetByID(id));
     }

    //Ihelper h = b.RetrieveByID(5)       
    public static IHelper RetrieveByID(this ObjectB b, int id)
     { 
          return new HelperB(b.GetById(id.ToString())); 
     }
 }

كيف يمكنني نشر تعليقات على Stack Overflow؟تعديل مشاركتي الأصلية أو نشر "إجابة"؟على أي حال، أعتقد أنه قد يكون من المفيد إعطاء مثال لما يحدث في AHelper.RetrieveByID() وBHelper.RetreiveByID()

في الأساس، تتعارض كلتا الطريقتين مع خدمة ويب تابعة لجهة خارجية تقوم بإرجاع كائنات عامة (قابلة للتحويل) مختلفة باستخدام طريقة استعلام تأخذ سلسلة SQL زائفة كمعلماتها الوحيدة.

لذا، قد يبدو AHelper.RetrieveByID(معرف السلسلة) هكذا

public static AObject RetrieveByID(string ID)
{
  QueryResult qr = webservice.query("SELECT Id,Name FROM AObject WHERE Id = '" + ID + "'");

  return (AObject)qr.records[0];
}

public static BObject RetrieveByID(string ID)
{
  QueryResult qr = webservice.query("SELECT Id,Name,Company FROM BObject WHERE Id = '" + ID + "'");

  return (BObject)qr.records[0];
}

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

أوه، وروب، أنا أتفق تمامًا - وهذا على الأرجح يمثل قيدًا على تصميمي وليس اللغة.:)

هل تبحث عن سلوك متعدد الأشكال؟ثم ستحتاج إلى الواجهة والمنشئ العادي.ما هو الأمر غير البديهي في استدعاء المُنشئ؟إذا لم تكن بحاجة إلى تعدد الأشكال (يبدو أنك لا تستخدمه الآن)، فيمكنك الالتزام بأساليبك الثابتة.إذا كانت هذه جميعها عبارة عن أغلفة حول مكون بائع، فربما تحاول استخدام طريقة المصنع لإنشائها مثل VendorBuilder.GetVendorThing("A") والتي يمكنها إرجاع كائن من النوع IVendorWrapper.

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

com.rptony نقطة جيدة بشأن مشكلات المزامنة المحتملة مع الإحصائيات، وهي مشكلة لم أذكرها، لذا شكرًا لك :) أيضًا، إنها Rob كوبر (وليس النحاس) راجع للشغل ;) :D ( يحرر: اعتقدت أنني سأذكر ذلك في حالة حدوث ذلك لم يكن كذلك خطأ مطبعي، أتوقع ذلك، لذا لا توجد مشكلة!)

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