java لماذا لا تسمح جافا بإلغاء الأساليب الثابتة؟




static override (18)

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

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;

class RegularEmployee {

    private BigDecimal salary = BigDecimal.ONE;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }
    public BigDecimal calculateBonus() {
        return salary.multiply(this.getBonusMultiplier());
    }
    public BigDecimal calculateOverridenBonus() {
        try {
            // System.out.println(this.getClass().getDeclaredMethod(
            // "getBonusMultiplier").toString());
            try {
                return salary.multiply((BigDecimal) this.getClass()
                    .getDeclaredMethod("getBonusMultiplier").invoke(this));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }
    // ... presumably lots of other code ...
}

final class SpecialEmployee extends RegularEmployee {

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

public class StaticTestCoolMain {

    static public void main(String[] args) {
        RegularEmployee Alan = new RegularEmployee();
        System.out.println(Alan.calculateBonus());
        System.out.println(Alan.calculateOverridenBonus());
        SpecialEmployee Bob = new SpecialEmployee();
        System.out.println(Bob.calculateBonus());
        System.out.println(Bob.calculateOverridenBonus());
    }
}

الناتج الناتج:

0.02
0.02
0.02
0.03

ما كنا نحاول تحقيقه :)

حتى إذا أعلنا متغيرًا ثالثًا لـ Carl كـ RegularEmployee وقمت بتعيينه للمثال SpecialEmployee ، فستظل لدينا استدعاء طريقة RegularEmployee في الحالة الأولى واستدعاء طريقة SpecialEmployee في الحالة الثانية

RegularEmployee Carl = new SpecialEmployee();

System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());

مجرد إلقاء نظرة على وحدة التحكم الإخراج:

0.02
0.03

؛)

لماذا لا يمكن تجاوز الأساليب الثابتة؟

إذا أمكن ، يرجى استخدام مثال.


Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it (which is the case with overriden static methods). As static methods are class methods they are notinstance methods so they have nothing to do with the fact which reference is pointing to which Object or instance.as per the nature of static method it belongs to specific class, but you can redeclare it in to the subclass but that subclass doesn't know anything about the parent class' static methods because as I said it is specific to only that class in which it has been declared .Accessing them using object references is just an extra liberty given by the designers of Java and we should certainly not think of stopping that practice only when they restrict it more details and example http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html


Answer of this question is simple, the method or variable marked as static belongs to the class only, So that static method cannot be inherited in the sub class because they belong to the super class only.


يتم جعل تجاوز الأسلوب ممكنًا من خلال الإرسال الديناميكي ، مما يعني أن نوع الكائن المحدد لا يحدد سلوكه ، ولكن نوع وقت التشغيل الخاص به:

Animal lassie = new Dog();
lassie.speak(); // outputs "woof!"
Animal kermit = new Frog();
kermit.speak(); // outputs "ribbit!"

على الرغم من أنه يتم lassie و kermit ككائنات من نوع Animal ، يختلف سلوكها (method .speak() ) لأن .speak() الديناميكي سوف يقوم فقط bind استدعاء الأسلوب .speak() بالتنفيذ في وقت التشغيل - وليس في وقت التحويل البرمجي.

الآن ، هنا حيث تبدأ الكلمة الأساسية static بالمعنى: الكلمة "static" هي معنى متناقض لـ "dynamic". لذلك السبب لا يمكنك تجاوز الأساليب الثابتة لأنه لا يوجد إرسال ديناميكي على أعضاء ثابت - لأن كلمة static تعني حرفيا "غير ديناميكية". إذا أرسلوا بشكل ديناميكي (وبالتالي يمكن أن يتم تجاوزه) فإن الكلمة الأساسية static لن تكون مجدية بعد الآن.


The following code shows that it is possible:

class OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriden Meth");   
}   

}   

public class OverrideStaticMeth extends OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriding Meth");   
}   

public static void main(String[] args) {   
OverridenStaticMeth osm = new OverrideStaticMeth();   
osm.printValue();   

System.out.println("now, from main");
printValue();

}   

} 

Here is a simple explanation.A static method is associated with a class while an instance method is associated with a particular object.Overrides allow to call different implementation of the overridden methods associated with the particular object. So it is counter-intuitive to override static method which is not even associated with objects but class itself in the first place.So static methods cannot be overridden based on what object is calling it, it will always be associated with the class where it was created.


Easy solution: Use singleton instance. It will allow overrides and inheritance.

In my system, I have SingletonsRegistry class, which returns instance for passed Class. If instance is not found, it is created.

Haxe language class:

package rflib.common.utils;
import haxe.ds.ObjectMap;



class SingletonsRegistry
{
  public static var instances:Map<Class<Dynamic>, Dynamic>;

  static function __init__()
  {
    StaticsInitializer.addCallback(SingletonsRegistry, function()
    {
      instances = null;
    });

  } 

  public static function getInstance(cls:Class<Dynamic>, ?args:Array<Dynamic>)
  {
    if (instances == null) {
      instances = untyped new ObjectMap<Dynamic, Dynamic>();      
    }

    if (!instances.exists(cls)) 
    {
      if (args == null) args = [];
      instances.set(cls, Type.createInstance(cls, args));
    }

    return instances.get(cls);
  }


  public static function validate(inst:Dynamic, cls:Class<Dynamic>)
  {
    if (instances == null) return;

    var inst2 = instances[cls];
    if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!";
  }

}

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


الإجابة المختصرة هي: أنه ممكن تمامًا ، لكن جافا لا تفعل ذلك.

إليك بعض التعليمات البرمجية التي توضح الحالة الراهنة في Java:

ملف Base.java :

package sp.trial;
public class Base {
  static void printValue() {
    System.out.println("  Called static Base method.");
  }
  void nonStatPrintValue() {
    System.out.println("  Called non-static Base method.");
  }
  void nonLocalIndirectStatMethod() {
    System.out.println("  Non-static calls overridden(?) static:");
    System.out.print("  ");
    this.printValue();
  }
}

ملف Child.java :

package sp.trial;
public class Child extends Base {
  static void printValue() {
    System.out.println("  Called static Child method.");
  }
  void nonStatPrintValue() {
    System.out.println("  Called non-static Child method.");
  }
  void localIndirectStatMethod() {
    System.out.println("  Non-static calls own static:");
    System.out.print("  ");
    printValue();
  }
  public static void main(String[] args) {
    System.out.println("Object: static type Base; runtime type Child:");
    Base base = new Child();
    base.printValue();
    base.nonStatPrintValue();
    System.out.println("Object: static type Child; runtime type Child:");
    Child child = new Child();
    child.printValue();
    child.nonStatPrintValue();
    System.out.println("Class: Child static call:");
    Child.printValue();
    System.out.println("Class: Base static call:");
    Base.printValue();
    System.out.println("Object: static/runtime type Child -- call static from non-static method of Child:");
    child.localIndirectStatMethod();
    System.out.println("Object: static/runtime type Child -- call static from non-static method of Base:");
    child.nonLocalIndirectStatMethod();
  }
}

إذا قمت بتشغيل هذا (قمت به على جهاز Mac ، من Eclipse ، باستخدام Java 1.6) ، فإنك تحصل على:

Object: static type Base; runtime type Child.
  Called static Base method.
  Called non-static Child method.
Object: static type Child; runtime type Child.
  Called static Child method.
  Called non-static Child method.
Class: Child static call.
  Called static Child method.
Class: Base static call.
  Called static Base method.
Object: static/runtime type Child -- call static from non-static method of Child.
  Non-static calls own static.
    Called static Child method.
Object: static/runtime type Child -- call static from non-static method of Base.
  Non-static calls overridden(?) static.
    Called static Base method.

هنا ، يبدو أن الحالات الوحيدة التي قد تكون مفاجأة (والتي يدور حولها السؤال) هي الحالة الأولى :

"لا يتم استخدام نوع وقت التشغيل لتحديد أي الطرق الثابتة تسمى ، حتى عند استدعاء مثيل كائن ( obj.staticMethod() )."

والحالة الأخيرة :

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

الاتصال مع مثيل كائن

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

الاتصال من داخل طريقة الكائن

يتم حل استدعاءات أسلوب الكائن باستخدام نوع وقت التشغيل ولكن يتم حل استدعاءات الأسلوب ( فئة ) ثابتة باستخدام نوع وقت التحويل البرمجي (تم التصريح به).

تغيير القواعد

لتغيير هذه القواعد ، بحيث آخر استدعاء في المثال يسمى Child.printValue() ، يجب توفير استدعاءات ثابتة مع نوع في وقت التشغيل ، بدلاً من المحول البرمجي حل المكالمة في وقت التحويل البرمجي مع الفئة المعتمد من الكائن (أو السياق). باستطاعة مكالمات ثابتة أن تستخدم التسلسل الهرمي للنوع (الديناميكي) لحل المكالمة ، كما تفعل مكالمات أسلوب الكائن اليوم.

هذا من شأنه أن يكون قابلاً للتنفيذ بسهولة (إذا قمنا بتغيير Java: -O) ، وهو ليس غير معقول على الإطلاق ، ومع ذلك ، فإنه يحتوي على بعض الاعتبارات المثيرة للاهتمام.

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

في هذه اللحظة ، Java هذا " obj.staticMethod() " في اللغة حيث يتم استبدال استدعاءات obj.staticMethod() استدعاءات ObjectClass.staticMethod() (عادةً مع تحذير). [ ملاحظة: ObjectClass هو نوع وقت التحويل obj .] سيكون هؤلاء مرشحين جيدين للتجاوز بهذه الطريقة ، مع أخذ نوع وقت التشغيل من obj .

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

الطرق الأخرى من استدعاء أسلوب ثابت أكثر this.staticMethod() : يجب أن يعني هذا obj.staticMethod() نفس obj.staticMethod() ، أخذ نوع وقت التشغيل this . ومع ذلك ، قد يسبب هذا بعض الصداع مع البرامج الموجودة ، والتي تستدعي أساليب (على ما يبدو المحلية المحلية) دون زخرفة (التي يمكن القول أنها تعادل هذا. this.method() ).

فماذا عن المكالمات unadorned staticMethod() ؟ أقترح أن يفعلوا نفس الشيء مثل اليوم ، واستخدم سياق الصف المحلي لتحديد ما يجب القيام به. وإلا فإن ارتباكًا كبيرًا سيترتب على ذلك. وبالطبع ، فإن هذا يعني أن method() تعني هذا. this.method() إذا كانت method غير ثابتة ، و ThisClass.method() إذا كانت الطريقة طريقة ثابتة. هذا هو مصدر آخر للالتباس.

اعتبارات أخرى

إذا قمنا بتغيير هذا السلوك (وجعلنا الاستدعاءات الثابتة يحتمل أن تكون ديناميكية غير محلية) ، فإننا ربما نرغب في إعادة النظر في المعنى final private protected كمؤهلات على الطرق static للفئة. يجب علينا جميعًا أن نعتاد على حقيقة أن الطرق public final private static public final لا يتم تجاوزها ، وبالتالي يمكن حلها بشكل آمن في وقت الترجمة ، وتكون "آمنة" للقراءة كمراجع محلية.


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

مثال : لنحاول معرفة ما يحدث إذا حاولنا تجاوز طريقة ثابتة: -

class SuperClass {
// ......
public static void staticMethod() {
    System.out.println("SuperClass: inside staticMethod");
}
// ......
}

public class SubClass extends SuperClass {
// ......
// overriding the static method
public static void staticMethod() {
    System.out.println("SubClass: inside staticMethod");
}

// ......
public static void main(String[] args) {
    // ......
    SuperClass superClassWithSuperCons = new SuperClass();
    SuperClass superClassWithSubCons = new SubClass();
    SubClass subClassWithSubCons = new SubClass();

    superClassWithSuperCons.staticMethod();
    superClassWithSubCons.staticMethod();
    subClassWithSubCons.staticMethod();
    // ...
}
}

الإخراج : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod

لاحظ السطر الثاني من الإخراج. لو تم تجاوز staticMethod كان يجب أن يكون هذا الخط متطابقًا مع السطر الثالث حيث إننا نستدعي 'staticMethod ()' على كائن من نوع Runtime كـ 'SubClass' وليس كـ 'SuperClass'. هذا يؤكد أن الطرق الثابتة يتم حلها دائمًا باستخدام معلومات نوع وقت التحويل فقط.


Now seeing above answers everyone knows that we can't override static methods, but one should not misunderstood about the concept of accessing static methods from subclass .

We can access static methods of super class with subclass reference if this static method has not been hidden by new static method defined in sub class.

For Example, see below code:-

public class StaticMethodsHiding {
    public static void main(String[] args) {
        SubClass.hello();
    }
}


class SuperClass {
    static void hello(){
        System.out.println("SuperClass saying Hello");
    }
}


class SubClass extends SuperClass {
    // static void hello() {
    // System.out.println("SubClass Hello");
    // }
}

انتاج:-

SuperClass saying Hello

See Java oracle docs and search for What You Can Do in a Subclass for details about hiding of static methods in sub class.

شكر


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

public class RegularEmployee {
    private BigDecimal salary;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }

    public BigDecimal calculateBonus() {
        return salary.multiply(getBonusMultiplier());
    }

    /* ... presumably lots of other code ... */
}

public class SpecialEmployee extends RegularEmployee {
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

لن يعمل هذا الرمز كما قد تتوقع. أي أن SpecialEmployee تحصل على مكافأة 2٪ مثل الموظفين العاديين. ولكن إذا قمت بإزالة s "ثابت" ، عندئذ تحصل SpecialEmployee على مكافأة بنسبة 3٪.

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

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

لكنها لا تعمل.

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

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

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

تحديث

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

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


بشكل عام ، من غير المنطقي السماح بـ "تجاوز" الطرق الثابتة حيث لن تكون هناك طريقة جيدة لتحديد أي شخص يتم الاتصال به في وقت التشغيل. مع أخذ مثال الموظف ، إذا اتصلنا بـ RegularEmployee.getBonusMultiplier () - ما الطريقة التي من المفترض أن يتم تنفيذها؟

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


في Java (وكثير من لغات OOP ، لكن لا يمكنني التحدث للجميع ؛ والبعض الآخر ليس ثابتًا على الإطلاق) جميع الطرق لها توقيع ثابت - المعلمات وأنواعها. في الطريقة الافتراضية ، يتم تضمين المعلمة الأولى: مرجع إلى الكائن نفسه وعند استدعاء من داخل الكائن ، يضيف المحول البرمجي تلقائيًا this .

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

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

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

كما سأل شخص ما في تعليق على ما هو سببك والغرض من رغبتك في الحصول على هذه الميزة؟

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

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

تعديل : تعليق واحد آخر. الآن بعد أن رأيت الاختلافات وأنا مطور جافا / جيم # بنفسي ، يمكنني أن أفهم لماذا قد تكون الإجابات التي تحصل عليها من مطوري جافا مربكة إذا كنت قادمًا من لغة مثل روبي. لا تعتبر أساليب Java static هي نفس أساليب class Ruby. سوف يواجه مطورو جافا صعوبة في فهم ذلك ، كما هو الحال مع أولئك الذين يعملون في الغالب بلغة مثل Ruby / Smalltalk. أستطيع أن أرى كيف أن هذا من شأنه أيضا أن يكون مربكا إلى حد كبير من حقيقة أن جافا يستخدم أيضا "طريقة الطبقة" كطريقة أخرى للحديث عن أساليب ثابتة ولكن هذا المصطلح نفسه يستخدم بشكل مختلف من قبل روبي. لا يحتوي Java على أساليب فئة نمط Ruby (عذرًا)؛ ليس لدى Ruby أساليب ثابتة لنمط Java وهي بالفعل وظائف نمط إجرائي قديمة ، كما هو مذكور في C.

بالمناسبة - شكرا على السؤال! تعلمت شيئا جديدا بالنسبة لي اليوم عن طرق الطبقية (أسلوب روبي).


By overriding we can create a polymorphic nature depending on the object type. Static method has no relation with object. So java can not support static method overriding.


What good will it do to override static methods. You cannot call static methods through an instance.

MyClass.static1()
MySubClass.static1()   // If you overrode, you have to call it through MySubClass anyway.

EDIT : It appears that through an unfortunate oversight in language design, you can call static methods through an instance. Generally nobody does that. My bad.


By overriding, you achieve dynamic polymorhpism. When you say overridng static methods, the words you are trying to use are contradictory.

Static says - compile time, overriding is used for dynamic polymorphism. Both are opposite in nature, and hence can't be used together.

Dynamic polymorhpic behavior comes when programmer uses an object and accessing an instance method. JRE will map different instance methods of different classes based on what kind of object you are using.

When you say overriding static methods, static methods we will access by using class name, which will be linked at compile time, so there is no concept of linking methods at run time with static methods. So the term "overriding" static methods itself doesn't make any meaning.

Note: even if you access a class method with an object, still java compiler is intelligent enough to find it out, and will do static linking.


Yes..Practically Java's Allows to override static method...And No Theoretically......If you Override a static method in Java then it will compile and run smoothly..but it will lose Polymorphism....which is basic property of Java ..You will Read Everywhere that its not possible try yourself compling and running..you will get your answer...eg.If you Have Class Animal and a static method eat() and you Override that static method in its Subclass lets called it Dog..then when wherever you Assign a Dog object to an Animal Reference and call eat()..according to Java Dog's eat() should have been called..but in static Overriding Animals's eat() will Called..

class Animal {
    public static void eat() {
        System.out.println("Animal Eating");
    }
}

class Dog extends Animal{
    public static void eat() {
        System.out.println("Dog Eating");
    }
}

class Test {
    public static void main(String args[]) {
       Animal obj= new Dog();//Dog object in animal
       obj.eat(); //should call dog's eat but it didn't
    }
}


Output Animal Eating

According to Polymorphism Principle of Java the Output Should be Dog Eating .
But the result was different because to support Polymorphism Java uses Late Binding that means methods are called only at the run-time but not in the case of static methods..In static methods compiler calls methods at the compile time rather than the run-time..so we get methods according to the reference and not according to the object a reference a containing..that's why You can say Practically it supports static overring but theoretically it doesn't...





static-methods