Why is it not possible to override static methods?
If possible, please use an example.
Why is it not possible to override static methods?
If possible, please use an example.
Overriding depends on having an instance of a class. The point of polymorphism is that you can subclass a class and the objects implementing those subclasses will have different behaviors for the same methods defined in the superclass (and overridden in the subclasses). A static method is not associated with any instance of a class so the concept is not applicable.
Static methods are treated as global by the JVM, there are not bound to a class at all.
It could conceptually be possible if class somehow existed as object in the JVM (like in languages like Smalltalk) but it's not the case in Java.
EDIT
You can overlaod static method, that's ok. But you can not override a static method, because class are no first-class object. You can use reflection to get the class of an object at run-time, but the object that you get does not parallel the class hierarchy.
class MyClass { ... }
class MySubClass extends MyClass { ... }
MyClass obj1 = new MyClass();
MySubClass obj2 = new MySubClass();
ob2 insteanceof MyClass --> true
Class clazz1 = obj1.getClass();
Class clazz2 = obj2.getClass();
clazz2 insteanceof clazz1 --> false
You can reflects on them but it stops there. You don't invoke a static method by using clazz1.staticMethod()
, but using MyClass.staticMethod()
. A static method is not bound to an object and there is hence no notion of this
nor super
in a static method. A static method is a global function. By consequence there is also no notion of polymorphism and method override make no sense.
But this could be possible if MyClass
was an object at run-time on which you invoke a method, as in Smalltalk (or maybe JRuby as one comment suggest, but I know nothing of JRuby).
Oh yeah... one more stuff. You can invoke a static method through an object obj1.staticMethod()
but that really a syntactic hack for MyClass.staticMethod()
and should be avoided. It usually raises a warning in modern IDE. I don't know why they introduced this shortcut at first.
overriding is reserved for instance members to support polymorphic behaviour. static class members do not belong to a particular instance. instead, static members belong to the class and as a result overriding is not supported because subclasses only inherit protected and public instance members and not static members. You may want to define an inerface and research factory and/or strategy design patterns to evaluate an alternate approach.
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.
Personally I think this is a flaw in the design of Java. Yes, yes, I understand that non-static methods are attached to an instance while static methods are attached to a class, etc etc. Still, consider the following code:
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");
}
}
This code will not work as you might expect. Namely, SpecialEmployee's get a 2% bonus just like regular employees. But if you remove the "static"s, then SpecialEmployee's get a 3% bonus.
(Admittedly, this example is poor coding style in that in real life you would likely want the bonus multiplier to be in a database somewhere rather than hard-coded. But that's just because I didn't want to bog down the example with a lot of code irrelevant to the point.)
It seems quite plausible to me that you might want to make getBonusMultiplier static. Perhaps you want to be able to display the bonus multiplier for all the categories of employees, without needing to have an instance of an employee in each category. What would be the point of searching for such example instances? What if we are creating a new category of employee and don't have any employees assigned to it yet? This is quite logically a static function.
But it doesn't work.
And yes, yes, I can think of any number of ways to rewrite the above code to make it work. My point is not that it creates an unsolvable problem, but that it creates a trap for the unwary programmer, because the language does not behave as I think a reasonable person would expect.
Perhaps if I tried to write a compiler for an OOP language, I would quickly see why implementing it so that static functions can be overriden would be difficult or impossible.
Or perhaps there is some good reason why Java behaves this way. Can anyone point out an advantage to this behavior, some category of problem that is made easier by this? I mean, don't just point me to the Java language spec and say "see, this is documented how it behaves". I know that. But is there a good reason why it SHOULD behave this way? (Other than "making it work right was too hard".)
Update
@VicKirk: If you mean that this is "bad design" because it doesn't fit how Java handles statics, my reply is, "Well, duh, of course." As I said in my original post, it doesn't work. But if you mean that it is bad design in the sense that there would be something fundamentally wrong with a language where this worked, i.e. where statics could be overridden just like virtual functions, that this would somehow introduce an ambiguity or it would be impossible to implement efficiently or some such, I reply, "Why? What's wrong with the concept?"
I think the example I give is a very natural thing to want to do. I have a class that has a function that does not depend on any instance data, and which I might very reasonably want to call independent of an instance, as well as wanting to call from within an instance method. Why should this not work? I've run into this situation a fair number of times over the years. In practice I get around it by making the function virtual, and then creating a static method whose only purpose in life is to be a static method that passes the call on to the virtual method with a dummy instance. That seems like a very roundabout way to get there.
In general it doesn't make sense to allow 'overriding' of static methods as there would be no good way to determine which one to call at runtime. Taking the Employee example, if we call RegularEmployee.getBonusMultiplier() - which method is supposed to be executed?
In the case of Java, one could imagine a language definition where it is possible to 'override' static methods as long as they are called through an object instance. However, all this would do is to re-implement regular class methods, adding redundancy to the language without really adding any benefit.
In Java (and many OOP languages, but I cannot speak for all; and some do not have static at all) all methods have a fixed signature - the parameters and types. In a virtual method, the first parameter is implied: a reference to the object itself and when called from within the object, the compiler automatically adds this
.
There is no difference for static methods - they still have a fixed signature. However, by declaring the method static you have explicitly stated that the compiler must not include the implied object parameter at the beginning of that signature. Therefore, any other code that calls this must must not attempt to put a reference to an object on the stack. If it did do that, then the method execution would not work since the parameters would be in the wrong place - shifted by one - on the stack.
Because of this difference between the two; virtual methods always have a reference to the context object (i.e. this
) so then it is possible to reference anything within the heap that belong to that instance of the object. But with static methods, since there is no reference passed, that method cannot access any object variables and methods since the context is not known.
If you wish that Java would change the definition so that a object context is passed in for every method, static or virtual, then you would in essence have only virtual methods.
As someone asked in a comment to the op - what is your reason and purpose for wanting this feature?
I do not know Ruby much, as this was mentioned by the OP, I did some research. I see that in Ruby classes are really a special kind of object and one can create (even dynamically) new methods. Classes are full class objects in Ruby, they are not in Java. This is just something you will have to accept when working with Java (or C#). These are not dynamic languages, though C# is adding some forms of dynamic. In reality, Ruby does not have "static" methods as far as I could find - in that case these are methods on the singleton class object. You can then override this singleton with a new class and the methods in the previous class object will call those defined in the new class (correct?). So if you called a method in the context of the original class it still would only execute the original statics, but calling a method in the derived class, would call methods either from the parent or sub-class. Interesting and I can see some value in that. It takes a different thought pattern.
Since you are working in Java, you will need to adjust to that way of doing things. Why they did this? Well, probably to improve performance at the time based on the technology and understanding that was available. Computer languages are constantly evolving. Go back far enough and there is no such thing as OOP. In the future, there will be other new ideas.
EDIT: One other comment. Now that I see the differences and as I Java/C# developer myself, I can understand why the answers you get from Java developers may be confusing if you are coming from a language like Ruby. Java static
methods are not the same as Ruby class
methods. Java developers will have a hard time understanding this, as will conversely those who work mostly with a language like Ruby/Smalltalk. I can see how this would also be greatly confusing by the fact that Java also uses "class method" as another way to talk about static methods but this same term is used differently by Ruby. Java does not have Ruby style class methods (sorry); Ruby does not have Java style static methods which are really just old procedural style functions, as found in C.
By the way - thanks for the question! I learned something new for me today about class methods (Ruby style).