views:

945

answers:

7

Why is it not possible to override static methods?

If possible, please use an example.

+44  A: 

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.

Nathan Hughes
very precise and exact answer.
Abhishek Jain
+6  A: 

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.

ewernli
Even many modern languages like Ruby have class-methods and allow overriding them.
Chandru
Classes do exist as objects in Java. See the "Class" class. I can say myObject.getClass() and it will return me an instance of the appropriate class object.
Jay
You get only a "description" of the class -- not the class itself. But the difference is subtle.
ewernli
You still have class but it is hidden in the VM (near the class loader), user have almost no access to it.
mathk
+2  A: 

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.

Athens
A: 

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.

fastcodejava
"You cannot call static methods through an instance" Actually, one of Java's quirks is that you CAN call static methods through an instance, even though it's an exceedingly bad idea.
R. Bemrose
+5  A: 

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.

Jay
Although this code works in Java, it's a quirk of Java, which lets you call static methods on an instance. It would fail in C#, because C# doesn't allow you to call static methods as an instance method like you're doing on the `salary.multiply` line.
R. Bemrose
This example is just a bad design and does not highlight any 'flaw' with the implementation of static methods. I can't think of any example where I would want to override them, would you really want to write code like bonus = (obj instanceof B) ? B.bonus() : A.bonus(). What if it was overridden on type C, or a third party adds type D, every bit of code that uses the methods is then broken. True you could write the above with an instance variable but then it would be an instance method, as it then requires an instance to resolve the method!
vickirk
BTW, as things are instance.staticMethod() is likely to be optimised with IntanceClass.staticMethod()
vickirk
Class are not first-class entity in java. You can call a static method with `obj.staticMethod()` or `staticMethod()` but the compiler treats that as `MyClass.staticMethod()` depending on the scope it is compiled. You should always use `MyClass.staticMethod()` to avoid the confusion that you just described. See my answer which I refined.
ewernli
@Bemrose: But that's my point: Why shouldn't I be allowed to do that? Maybe my intuitive concept of what a "static" should do is different from yours, but basically I think of a static as a method that CAN be static because it doesn't use any instance data, and which SHOULD be static because you may want to call it independently of an instance. A static is clearly tied to a class: I expect Integer.valueOf to be tied to Integers and Double.valueOf to be tied to Doubles.
Jay
@Jay: Honestly, you shouldn't. I don't know why the developers of Java decided to do it that way. It's basically a compiler trick, as vickirk implied.
R. Bemrose
Jay
Jay, regarding your last comment, it would make much more sense to have the instance method call the static method and have the implementation in the static method. Why create an instance when you don't need one?
Yishai
I think that ultimately this code is confusing. Consider if the instance is passed as a parameter. Then you are saying that the runtime instance should dictate which static method is called. That basically makes a whole separate hierarchy parallel to the existing instance one. Now what if a subclass defines the same method signature as non-static? I think that the rules would make things quite complicated. It is precisely these kinds of language complications that Java tries to avoid.
Yishai
@Yishai: RE "Runtime instance dictate which static method is called": Exactly. I don't see why you can't do anything with a static that you can do with a virtual. "Separate hierarchy": I'd say, Make it part of the same hierarchy. Why aren't statics included in the same hierarchy? "Subsclass defines the same signature non-static": I presume that would be illegal, just like it's illegal to, say, have a subclass override a function with an identical signature but a different return type, or to not throw all the exceptions that the parent throws, or to have a narrower scope.
Jay
I put the real logic in a virtual and create a static to call it with a dummy object, rather than putting the real logic in a virtual, because the whole point is that I need to override the logic in a subclass, and Java doesn't allow me to override a static.
Jay
"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" - but it depends on what type the instance of an object is. How could you possibly call the correct method if you don't know what type of object it is, polymorphism is not driven by object state, rather than the behavior an instance exhibits.
vickirk
If I want to call a static function without having an instance, then yes, of course I have to specify the class. It seems very natural to me that I should be able to call a static function via a class name and either a static or virtual function via an object instance. Why not?
Jay
PS I don't want to circle around an argument forever. If we disagree, at some point we have to just say, "Okay, we disagree and neither is about to convince the other." But if you two want to continue to trade comments, I'm game.
Jay
But surely if you need an instance of an object to resolve which static method to call it is just not a static method. "Okay, we disagree and neither is about to convince the other." - I'm going to leave it at that :-)
vickirk
But I'll give a couple of upvotes for an interesting discussion!
Jay
I think Jay has a point - it surprised me too when I discovered that statics could not be overridden. In part because if I have A with method `someStatic()` and B extends A, then `B.someMethod()` *binds* to the method in A. If I subsequently add `someStatic()` to B, the calling code still invokes `A.someStatic()` until I recompile the calling code. Also it surprised me that `bInstance.someStatic()` uses the *declared* type of bInstance, not the runtime type because it binds at compile not link, so `A bInstance; ... bInstance.someStatic()` invokes A.someStatic() if if B.someStatic() exists.
Software Monkey
But ultimately, I find myself agreeing with vickirk: "surely if you need an instance of an object to resolve which static method to call it is just not a static method". I wish Java had never allowed static invocation via an instance reference, and I wish that they would now add a compiler lint switch to issue a warning for it.
Software Monkey
@SoftwareMonkey: I don't think it's inherently unreasonable to say that you CAN USE an instance to decide which static method to call. Yes, if you MUST HAVE an instance, then it's not a static any more. But to say that the compiler could examine the instance, see what class it is, and then use that to decide which static function ... seems quite reasonable to me. Again, see my example that started this argument ... I mean thread.
Jay
@Jay: That's the problem - the compiler can't examine the "instance" to see what it is, since the instance doesn't exist until runtime. The compiler can only invoke the static method based on the declared type, which could be the actual type or any of its super classes.
Software Monkey
@SoftwareMonkey: We're back to "is" versus "should be". Yes, what you are saying is how Java is. I'm not disputing that. But I see no reason why it couldn't choose a static method based on the runtime type, just as it chooses a virtual method based on the runtime type. Why couldn't static methods be included in the pointer table along with the virtual methods? Yes, this would mean there would be two ways to get to them. But so what?
Jay
+2  A: 

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.

Lars
Intuitively, I would think it should work just like a virtual function. If B extends A and both A and B have virtual functions named doStuff, the compiler knows that instances of A should use A.doStuff and instances of B should use B.doStuff. Why can't it do the same with static functions? After all, the compiler knows what class each object is an instance of.
Jay
Erm ... Jay, a static method need not be (generally is not) called on an instance ...
meriton
@meriton, but then it's even easier, no? If a static method is called using a classname, you'd use the method appropriate for the class.
CPerkins
But then what is overriding doing for you. If you call A.doStuff() should it use the version that was overridden in "B extends A" or the version that was overridden in "C extends A". And if you have C or B then you are calling those versions anyway... no overriding necessary.
PSpeed
@meriton: It is true that a static method is generally not called with an instance, but I presume that is because such a call does nothing useful given the current design of Java! I am suggesting that an alternative design might have been a better idea. BTW, in a very real sense static functions are called with an instance quite routinely: When you call the static function from within a virtual function. Then you implicitly get this.function(), i.e. the current instance.
Jay
@Jay: No, that is not true. The compiler will generate a different type of call. For all virtual method calls, the compiler puts a reference to `this` on the stack. With a static method call (even, unfortunately with Java's `this.staticMethod()`) there is no hidden reference so the compiler really strips off `this.` from that call.
Kevin Brock
@Kevin: Okay, my statement was poorly worded. I meant that if you call a static function from within the same class, you get the same function that you would get if you wrote "this.function()", i.e. the static in the "current" class, or the first one found as you chase up the hierarchy. (I think that's true: I'll have to check that out.) I did not mean to imply that it turned the call into a virtual call.
Jay
+1  A: 

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).

Kevin Brock
Of course, there's no reason why Java couldn't pass a "Class" object as a hidden parameter to static methods. It just wasn't designed to do it.
jmucchiello