oop - لماذا يجب ألا نستخدم static محمي في java



inheritance protected (7)

كنت أتناول هذا السؤال هل هناك طريقة لتجاوز متغيرات الصفوف في جافا؟ كان أول تعليق مع 36 upvotes:

إذا رأيت في أي وقت protected static ، protected static بتشغيل.

يمكن لأي شخص أن يفسر لماذا هو protected static استحم استياء؟


Answers

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

يتجنب بعض الناس عادة استخدام protected لأسباب مختلفة ، ويعتقد البعض أنه يجب تجنب المتغيرات static غير النهائية بكل الوسائل (أنا شخصيا أتعاطف مع الأخير إلى درجة ما) ، لذلك أعتقد أن الجمع بين protected static يجب أن تبدو سيئة ^ 2 إلى أولئك الذين ينتمون إلى كلتا المجموعتين.


إنه مستاء لأنه متناقض.

إن استخدام متغير متغير يعني ضمناً أنه سيتم استخدامه داخل الحزمة أو سيتم توريثه ضمن فئة فرعية .

جعل المتغير static يجعله عضوًا في الفصل ، مما يلغي نوايا الموروثة . هذا يترك فقط نية استخدام داخل الحزمة ، ولدينا package-private لهذا (أي تعديل).

الوضع الوحيد الذي يمكن أن أجده مفيدًا إذا كنت تعلن عن فصل دراسي يجب استخدامه لبدء تشغيل التطبيق (مثل إطلاق تطبيق JavaFX Application#launch ، وأردت فقط أن تكون قادرًا على الإطلاق من فئة فرعية. إذا فعلت ذلك ، فتأكد من الطريقة كما أنه final لعدم السماح hiding ، ولكن هذا ليس "القاعدة" ، وربما تم تنفيذه لمنع إضافة المزيد من التعقيد بإضافة طريقة جديدة لإطلاق التطبيقات.

للاطلاع على مستويات الوصول لكل معدل ، راجع ما يلي: برامج Java التعليمية - التحكم في الوصول إلى أعضاء الفئة


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

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

package a;
import java.util.List;

public abstract class BaseClass
{
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeDefaultB(list);
    }

    protected static Integer computeDefaultA(List<Integer> list)
    {
        return 12;
    }
    protected static Integer computeDefaultB(List<Integer> list)
    {
        return 34;
    }
}

مشتقة من ذلك:

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassA extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeOwnB(list);
    }

    private static Integer computeOwnB(List<Integer> list)
    {
        return 56;
    }
}

فئة أخرى مشتقة:

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassB extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeOwnA(list)+computeDefaultB(list);
    }

    private static Integer computeOwnA(List<Integer> list)
    {
        return 78;
    }
}

يمكن بالتأكيد أن يكون المعدل protected static مبررًا هنا:

  • يمكن أن تكون الطرق static ، لأنها لا تعتمد على متغيرات الحالة. وليس المقصود استخدامها مباشرة كطريقة متعددة الأشكال ، بل هي أساليب "مفيدة" تقدم تطبيقات افتراضية تشكل جزءاً من حساب أكثر تعقيداً ، وتعمل بمثابة "لبنات بناء" للتنفيذ الفعلي.
  • يجب ألا تكون الطرق public ، لأنها تفاصيل تنفيذ. ولا يمكن أن تكون private لأنه يجب أن يتم استدعاؤها من خلال فصول التمديد. كما لا يمكن أن يكون لديهم رؤية "افتراضية" ، لأنهم لن يكونوا متاحين لفصول التمديد في حزم أخرى.

(تحرير: يمكن للمرء أن يفترض أن التعليق الأصلي يشير فقط إلى الحقول ، وليس إلى الأساليب - ثم ، ومع ذلك ، كان عام جدا)


إنه شيء أكثر من مجرد مشكلة مباشرة. يقترح أنك لم تفكر بشكل صحيح من خلال ما يجري مع الفصل.

فكر في ما يعنيه static :

يوجد هذا المتغير على مستوى الفصل ، ولا يوجد بشكل منفصل لكل مثيل ولا يوجد له وجود مستقل في الفصول التي تمدني .

فكر في الوسائل protected :

يمكن مشاهدة هذا المتغير من خلال هذه الفئة ، الطبقات في نفس الحزمة والفئات التي تمتد لي .

المعنىان ليسا متنافيين تمامًا ولكنهما قريبان جدًا.

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

لتوسيع وشرح النقطة الأولى - جرب هذا المثال رمز:

public class Program {
    public static void main (String[] args) throws java.lang.Exception {
        System.out.println(new Test2().getTest());
        Test.test = "changed";
        System.out.println(new Test2().getTest());
    }
}

abstract class Test {
    protected static String test = "test";
}

class Test2 extends Test {
    public String getTest() {
        return test;
    }
}

سترى النتائج:

test
changed

جرب بنفسك على: https://ideone.com/KM8u8O

يمكن للفئة Test2 الوصول إلى test العضو الثابت من Test دون الحاجة إلى تأهيل الاسم - ولكنه لا يرث أو يحصل على نسخته الخاصة. انها تبحث في نفس المتغير بالضبط.


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


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


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

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

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

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





java oop inheritance static protected