طريقة ثابتة مقابل غير قابلة للثلاثة للطبقة غير القابلة للتغيير

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

  •  24-09-2019
  •  | 
  •  

سؤال

بالنظر إلى تعريف الفئة أدناه. كيف يمكن للمرء أن يحدث ما إذا كان ينبغي أن تكون أساليب الكعب ثابتة أم غير قاسية؟

class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // Should the methods add(), subtract() and inverseOf() be non-static ...

    public Point add(Point point) {

    }

    public Point subtract(Point point) {

    }

    public Point inverseOf() {

    }


    // Or static?

    public static Point add(Point point1, Point point2) {

    }

    public static Point subtract(Point point1, Point point2) {

    }

    public static Point inverseOf(Point point) {

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

المحلول

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

نصائح أخرى

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

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

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

من الناحية الدلالية ، يبدو أن النهج الثابت أكثر منطقية. سيعمل كلاهما بالطبع ، لكن النهج غير الاصطناعي يعطي الأسبقية لنقطة واحدة على الآخر ، وعلاوة على ذلك يعني أن النقطة 1 (الطريقة التي يتم استدعاؤها) قد يتم تعديلها نتيجة للمكالمة.

كمطور يستخدم فصولك ، إذا رأيت ما يلي:

Point p1 = new Point(1,2);
Point p2 = new Point(2,3);

p1.Add(p2);

أو..

Point p1 = new Point(1,2);
Point p2 = new Point(2,3);

Point.Add(p1, p2);

سيكون ميلي الطبيعي هو افتراض أن طريقة ADD () في الإصدار غير الأساسي تعدل Point1 لإضافة نتيجة النقطة 2. مع النهج الثابت ، يكون من الواضح (وإن لم يكن مضمونًا!) أن الطريقة نقية و لا يتم تعديل النقاط التمثيلية.

استخدم طريقة ثابتة عندما لا يعتمد جسم الطريقة على أي مثيل معين.

كمثال واحد ، انظر إلى الخاص بك add(Point, Point) طريقة. أنت تضيف معا الاثنين PointS التي تنتقل إلى الوظيفة كوسائط ، وإعادة أخرى Point. هل هذا يحتاج حقًا إلى داخلي this الإشارة إلى البعض Point?

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

تعديل: أعتقد أنني أسيء فهمه ، في الأصل. إذا نظرنا إلى الوراء ، لديك التوقيعات الصحيحة لكل من التطبيقات الثابتة وغير الستاطية. في هذه المرحلة ، أود أن أقول إنها مسألة أسلوب ، كما تعلم أن كلاهما سيعمل بشكل صحيح. كيف تريد استخدام فئة نقاطك؟ فكر فيما إذا كان يجعل الكود أكثر سهولة في القول Point a = Point.add(b, c) أو Point a = b.add(c). أنا شخصياً أحب الأول ، حيث يخبرني أنه لن يتم تعديل أي من المعاملات.

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

من الشائع تمامًا أن يكون لديك طرق مثل Add () وطرح () على فئة غير قابلة للتغيير تعيد مثيلات جديدة من الفئة غير القابلة للتغيير. هذا أسلوب جيد للبرمجة التي تشبه FP ومعقولة تمامًا لفئة مثل هذا. (انظر BigInteger أو BigDecimal للحصول على أمثلة جيدة. لا ترى التاريخ أو التقويم للحصول على أمثلة مخيفة سيئة. :)

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

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

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

بالنسبة إلى لغة مثل Java ، سأذهب مع أساليب ثابتة ، وتحديداً بسبب النقطة الثانية أعلاه. بالنسبة للغة التي تحتوي على زيادة الحمل (مثل Ruby) ، سأذهب مع طريقة مثيل للاستفادة من ذلك.

من الطبيعي أن تكون هذه الوظائف غير ثابتة. ولكن إذا كنت تشك في ، يرجى الرجوع إلى فهم ، فإنهم يصفون أشياء مثل هذا.

بالنسبة الى يمسك خبير المعلومات لا ينبغي أن تكون هذه الوظائف ثابتة.

على الرغم من عدم وجود معلومات مباشرة حول الطريقة الثابتة ، هناك

سيقودنا خبير المعلومات إلى وضع مسؤولية في الفصول الدراسية مع معظم المعلومات المطلوبة للوفاء بها.

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

سيؤدي إزالة ثابت إلى وضع المنطق أقرب إلى البيانات التي يستخدمها.

مما يجعلها ثابتة أيضًا يجعل من الصعب اختبارها! الإطار السخري الوحيد الذي أدركه في .NET الذي يمكنه التعامل مع هذا هو typemock.

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

يجب أن تكون هذه الأساليب ثابتة لأن الفصل نفسه يفسح المجال أمام أن يتم إنشاؤه عبر المُنشئ والقيم المعينة مرة واحدة بسبب كونها X و Y. هذا يعني أنه يمكنك إنشاء نقاط ، ولكن لا تتلاعب ببياناتهم للمضي قدمًا. أساليب ADD/Subtract/etc هي طرق فائدة لا يجب أن تتطلب مثيلًا للنقطة لاستخدامه.

في حالتك ، يجب أن تكون غير ثابتة ما لم تقم بتغيير التوقيع إلى public static Point add(Point point1, Point point2).

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

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