c# - تهيئة حقول الفئات في منشئ أو في الإعلان؟




java (9)

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

الدرس: لتهيئة الحقول الموروثة ، يمكنك القيام بذلك داخل المُنشئ.

لقد قمت بالبرمجة في C # وجافا مؤخرا وأنا أشعر بالفضول حيث أفضل مكان هو تهيئة حقول صفي.

هل يجب أن أفعل ذلك في الإعلان؟

public class Dice
{
    private int topFace = 1;
    private Random myRand = new Random();

    public void Roll()
    {
       // ......
    }
}

أو في منشئ؟

public class Dice
{
    private int topFace;
    private Random myRand;

    public Dice()
    {
        topFace = 1;
        myRand = new Random();
    }

    public void Roll()
    {
        // .....
    }
}

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


أنا عادة محاولة المنشئ لفعل أي شيء ولكن الحصول على التبعيات وتهيئة أعضاء مثيل ذات الصلة معهم. هذا سيجعل حياتك أسهل إذا كنت ترغب في وحدة اختبار الفصول الدراسية الخاصة بك.

إذا لم تتأثر القيمة التي ستقوم بتعيينها لمتغير مثيل بأي من المعلمات التي ستقوم بتمريرها لك منشئ ، قم بتعيينها في وقت التصريح.


تختلف دلالات C # قليلاً عن Java هنا. في C # التعيين في الإعلان يتم تنفيذ قبل استدعاء منشئ superclass. في Java يتم القيام به مباشرة بعد ذلك يسمح باستخدام هذا "" (مفيد بشكل خاص للفئات الداخلية المجهولة) ، ويعني أن دلالات هذين النموذجين تتطابق بالفعل.

إذا استطعت ، اجعل الحقول نهائية.


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


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


قواعدي:

  1. لا تقم بالتهيئة مع القيم الافتراضية في التعريف ( null ، false ، 0 ، 0.0 ...).
  2. تفضل التهيئة في تعريف إذا لم يكن لديك معلمة منشئ تقوم بتغيير قيمة الحقل.
  3. إذا تغيرت قيمة الحقل بسبب معلمة منشئ وضع التهيئة في المنشئات.
  4. كن متسقًا في ممارستك (القاعدة الأكثر أهمية).

ماذا لو أخبرتك ، هذا يعتمد؟

أنا بشكل عام تهيئة كل شيء والقيام بذلك بطريقة متسقة. نعم إنه صريح بشكل مفرط ولكنه سهل الصيانة.

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

في نظام الوقت الحقيقي ، أتساءل عما إذا كنت حتى بحاجة إلى متغير أو ثابت على الإطلاق.

وفي C ++ غالباً ما أقوم به إلى جانب عدم التهيئة في أي مكان ونقله إلى دالة Init (). لماذا ا؟ حسنا ، في C ++ إذا كنت تهيئة شيء ما يمكن أن يلقي استثناء أثناء بناء الكائن فتح نفسك على تسرب الذاكرة.


هناك العديد من الحالات المختلفة.

أنا فقط بحاجة إلى قائمة فارغة

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

public class CsvFile
{
    private List<CsvRow> lines = new List<CsvRow>();

    public CsvFile()
    {
    }
}

أنا أعلم القيم

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

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = new List<string>() {"usernameA", "usernameB"};
    }
}

أو

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = GetDefaultUsers(2);
    }
}

قائمة فارغة مع القيم الممكنة

في بعض الأحيان أتوقع قائمة فارغة افتراضيا مع إمكانية إضافة قيم من خلال منشئ آخر.

public class AdminTeam
{
    private List<string> usernames = new List<string>();

    public AdminTeam()
    {
    }

    public AdminTeam(List<string> admins)
    {
         admins.ForEach(x => usernames.Add(x));
    }
}

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

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

✓ مراعاة تهيئة الحقول الثابتة بدلاً من استخدام الصيغ الثابتة بشكل صريح ، لأن وقت التشغيل قادر على تحسين أداء الأنواع التي لا تحتوي على منشئ ثابت محدد بشكل واضح.

"النظر" في هذا السياق يعني أن تفعل ذلك ما لم يكن هناك سبب وجيه لعدم القيام بذلك. في حالة حقول تهيئة ثابتة ، قد يكون السبب الجيد هو أن التهيئة معقدة للغاية بحيث لا يمكن ترميزها مضمنة.





java