Call a specific class method in Java (without polymorphism)
I'm having a problem in Java. I have a method that can be extended. The problem is, that this method calls other methods of the class, and these can be extended as well.
Consider the following class:
public class Foo {
protected int xLast;
public updateMe(int x, int y) {
updateX(x);
}
protected updateX(int x) {
this.xLast = x;
}
}
This class is extended by the following class:
public class Bar extends Foo {
protected int xAverage = 0;
protected int xCount = 0;
protected int y;
public updateMe(int x, int y) {
super.updateMe(x, y);
updateX(x);
updateY(x);
}
protected updateX(int x) {
this.xAverage = (this.xAverage * this.xCount) + x;
this.xCount++;
this.xAverage /= xCount;
}
protected updateY(int y) {
this.y = y;
}
}
And also by this class:
public class Abc extends Foo {
}
When I do the following:
Foo myBar = new Bar();
myBar.updateMe(1, 2);
The Foo.updateX
method is not called, but the Bar.updateX
method is called twice. There are several solutions, some don't work well or are quite ugly:
- In
Bar.updateX
callsuper.updateX
. This will cause bothupdateX
methods to be called twice. - Remove the
updateX
call inFoo.updateMe
, forcing the extending classes to callsuper.updateX
. This will cause the classAbc
to have useless code that it doesn't need, or else the Abc class will not callupdateX
at all. - Rename the methods so that they do not override each other. This will work, but is not safe (in the future this might be forgotten and lead to problems) and is not enforced by the language.
I am aware that this is somewhat of a code-smell, but I see no better way to do this.
Basically I am looking to do something like this: in Foo.updateMe
I would like to call Foo.updateX
specifically, and not just the polymorph-ed updateX
.
I believe that something like the new
method keyword in C# can solve my problems开发者_运维技巧, but Java doesn't appear to have one, or any other way to accomplish this.
Edit:
In the end I chose just to rename the offending method. I have a just one method that causes this problem, and the solution suggested here, although sound from a design point-of-view will make this particular code harder to understand and maintain.
I'd do this:
- Remove updateX() call from Bar.updateMe() since updateX() is already called by super.updateMe().
- Call super.updateX() from Bar.updateX() since the method with the same name is supposed to extend functionality, not replace it.
In this case Abc won't have to be changed and both updateX() methods will be called once.
Java , all instance method calls are called by means of dynamic binding. As far as I know, there is no elegant way to accomplish what you want.
If you dont care about principles and elegance, you can check class of an instance at Foo.
public updateMe(int x, int y) {
if (getClass()==Foo.class)
updateX(x);
}
Eli, it seems that you would like to cancel OOP. First it is bad. If you need this change your design. Java is pure object oriented language and therefore all calls are polymorphic. If you extended your class and overrode some if its functionality it means that you need this and therefore this functionality should be called. This is the reason that updateX()
from Bar
is called.
BTW to do what you want you should create static method and call it this way: Foo.updateX().
You could also make updateX() private. Then a subclass that implements updateX() is "hiding", not "overriding" the method.
Drawbacks: Since updateX() is conceptually part of a Template pattern, it really "feels" like it should be protected.
You can't put
abstract private void updateX();
in the superclass to force users to implement it.
All implementations of updateMe() must always remember to call updateX()
Possible Drawback and possible advantage:
All of the private updateMe() methods will get called. (for me this this was desired, YMMV)
I recently faced this problem and chose this solution, though I considered renaming the methods and something very close to the (getClass()== MyFoo.class) trick. IMO all are reasonable.
精彩评论