Is it common practice to always use super for calling methods out of the superclass, even when I'm NOT overriding the method?
Assume
public class Parent{
public void method() {
}
}
So
public class Child extends Parent {
public void someMethod() {
super.method();
}
}
or
public class Child extends Parent {
public void someMethod() {
method();
}
}
Thanks for your input.
Calling super tells the JVM to explicitly look to the parent class' version of a method. Continuing with your example, if you just call
method()
The JVM will first search in the calling class for the method (in this case Child) before looking at the parent class. On the other hand, if you call
super.method()
then the JVM will explicitly look at the parent class for an implementation, even if Child has an method called method().
Putting these two ideas together, you should probably always use super when you intend to call the parent class' method. If your class does not override the method, then you could call without super. But even this becomes problematical if someone were to refactor your class later on and override the method.
The leading question is easy to answer:
Is it common practice to always use super for calling methods out of the superclass, even when I'm NOT overriding the method?
No, its not common practice. On the contrary, its dangerously confusing to do so. You call methods normally, because the main point of inheritance is to allow the classes to override methods to change/extend their behavior. You normally don't care about at which level a method is actually implemented.
The obvious exception is when you do override the method yourself and you want/need the parents functionality.
Now to the dangerously confusing part of explicitly calling super:
public class CallSuper {
static class Parent {
public void foo() {
System.out.println("Parent.foo");
}
/**
* Calls foo to do the main work
*/
public void bar() {
System.out.print
foo();
}
}
static class Child extends Parent {
public void foo() {
System.out.println("Child.foo");
}
public void bar() {
super.foo();
}
}
static class GrandChild extends Child {
public void foo() {
System.out.println("GrandChild.foo");
}
}
public static void main(String[] args) {
Parent p = new Parent();
Parent c = new Child();
Parent g = new GrandChild();
System.out.print("Parent.foo() = ");
p.foo();
System.out.print("Child.foo() = ");
c.foo();
System.out.print("GrandChild.foo() = ");
g.foo();
System.out.print("Parent.bar() = ");
p.bar();
System.out.print("Child.bar() = ");
c.bar();
System.out.print("GrandChild.bar() = ");
g.bar();
}
}
If you run this example it will output (added line numbers for clarity):
1 Parent.foo() = Parent.foo
2 Child.foo() = Child.foo
3 GrandChild.foo() = GrandChild.foo
4 Parent.bar() = Parent.foo
5 Child.bar() = Parent.foo
6 GrandChild.bar() = Parent.foo
The first four lines are not surprising, we get what foo implements at each level, respectively Parents's bar calling its foo. It starts to get odd at line 5. Child bypasses its own override of foo by calling super.bar(), so while its foo() is specialized, bar() is not. In Line 6, you see that GrandChild inherits this oddity from Child, so the somewhat innocent looking super.foo() in Child's bar has now broken GrandChild's expectations that its override of foo() is effective for all bar() as well.
Now if you imagine foo() and bar() actually doing something useful and that they have a meaningful relationship with each other, e.g. you are led to believe (either by Parent's documentation or just common sense) that overriding foo() will change the behavior of bar(), too. Child's "super" is breaking that.
As a rule of thumb, if you see a "super.x()" call anywhere outside of an actual override of "x()", its probably an accident lurking to happen.
Is it common practice to always use super for calling methods out of the superclass? Or is it redundant code?
It's not redundant. It have a special purpose of invoking parent class method (though you ovveriden). When you don't want, don't invoke. If you current class is not child of that class, super won't work for you.
Also if you call an overridden supermethod, does it use the supermethod or the lowest method?(in the inheritance tree)
The overridden method. Since you overridden it in your class.
If you're not overriding, let's talk about performance.
If you call an inherited method in your class, let's say, methodInSuperclass(), the JVM will look for that method first in your class, then up the class hierarchy until it finds it.
Using super.methodInSuperclass() tells the JVM to go directly to the superclass to look for that method.
So, using the super keyword improves performance by a few mills. It's ugly code, but it's not redundant as it will bring some performance improvement.
Consider using it if time is critical.
Calling the super method or not depends entirely on what you are trying to do. If you want to do what the parent class did plus some additional action, then calling the super method is good. If you're doing something completely different in the child implementation then do not call the super method. When you do call the super method in a hierarchy of classes, it calls the one closest to your child class in the hierarchy.
In some cases you may have an API where calling the super method is part of the overall contract. The clone method is such a case.
If Child is having the same version method with Parent, JVM will call the Child's version instead of Parent's version if without "super". The "super" keyword is helpful if you want to make sure the Child is always calling the Parent's version method.
Related
While refactoring I came across the following method in a subclass:
public void disposeResultsTable() {
super.disposeResultsTable();
}
What are the benefits to keeping this method rather than simply allowing the inherited superclass method to be called?
The only technical reason I can think of is what Michael proposed in the comments - making a restricted method become public.
However, I can think of a few human reasons.
For instance, this could be a convenient place to place a breakpoint for debugging invocations of disposeResultsTable of the child class. Or perhaps this was meant as a placeholder - "remember to implement this method for this class", or maybe someone wanted to explicitly point out to the reader of this code that this class uses the parent's implementation of disposeResultsTable. There are probably a bunch more options.
Have you tried looking up the history of this piece of code in the VCS? Maybe there's a helpful commit message from the original author.
The answer by Malt shows a common reason for overriding a method trivially by only calling the super implementation, namely to change the visibility from protected to public. Whether or not this might be the case in your example depends on the visibility of the respective method in the superclass...
However, there is another possible reason - although it might be a bit far-fetched and unusual - and this possible reason is reflection: The Class#getDeclaredMethods method only returns the methods that are... well, declared in this class.
For example, consider the following program:
import java.lang.reflect.Method;
public class TrivialOverride
{
static class BaseClass
{
void method0() {}
void method1() {}
}
static class ChildClass extends BaseClass
{
void method0() {}
}
public static void main(String[] args)
{
printDeclaredMethods(BaseClass.class);
printDeclaredMethods(ChildClass.class);
}
private static void printDeclaredMethods(Class<?> c)
{
System.out.println("Declared methods in " + c.getSimpleName());
for (Method m : c.getDeclaredMethods())
{
System.out.println(m.getName());
}
System.out.println();
}
}
The output is
Declared methods in BaseClass
method0
method1
Declared methods in ChildClass
method0
So method0 only appears in the list of declared methods of the child class because it was overridden from the base class.
In dynamic method binding a superclass reference can only call a subclass method which is inherited and overrode by it. However, the otherwise can be implemented.
abstract class in
{
abstract void print();
}
class a extends in
{
String name=this.getClass().getSimpleName();
void show()
{
System.out.println("class "+name);
}
void print()
{
show();
}
}
class Main
{
public static void main(String args[])
{
in x;
x = new a();
x.print();
}
}
Here, it prints successfully
class a
Also getClass() returns the subclass name instead of superclass name as this refers to the superclass object in main method.
A parent object reference is just constrained by the methods that it has in its class definition. If those methods are overridden by subclass, and at run time, if the actual object referred by the parent reference is of subclass type, then that overridden method is invoked. It doesn't matter if the overridden method invokes methods that are not originally present in the parent class or accesses the variables that are not present in the parent class.
This is what polymorphism is all about. It is by design meant to be this way as it makes program extension easier in case if we have different specific inheritance hierarchies where the parent class need not know the exact implementation of certain methods and can make things implemented by the subclasses as some sort of contract.
Future is unknown A developer writing a class A.java today can never predict in future the names or signatures of the methods which any other developer may include in his class extending A.java. Also such classes may be numerous with each having separate methods.
Base class should never be coupled with its sub classes. It must not care about how the sub classes are implemented.
Although it is not recommended but still if you wish to invoke the method defined in one of the sub class you may do it by typecasting like below.
public class Parent {
public class someMethod(){
if( this instanceof Child1){
((Child1)this).someAdditionalMethod();
}
}
}
public class Child1 extends Parent{
public class someAdditionalMethod(){
}
}
Suppose I have the following classes
Class Parent{
public void test(){
System.out.println("Parent");
}
}
Class Child extends Parent{
public void test(){
System.out.println("Child");
}
}
Parent parentE = new Child();
parentE.test();
((Parent)parentE).test();
Output is:
Child
Child
But how can I run parent method in this case using parentE reference?
When you override the parent method, the child object will always call the overriding method (child method) due to Polymorphism.
So in your case either you call the parent method explicitly, inside the child object:
Class Child extends Parent{
public void test(){
super.test();
}
}
Or make a Parent object and call it's method.
Parent parentE = new Parent();
parentE.test();
This is a key feature of polymorphism.
The object you instantiated is an instance of Child. Calling that object's test() is always going to result in the Child's (overridden) test() being called, even if you've assigned that instance to a variable of Parent type.
In short, this is how you can achieve more specific behavior while only having to reference the object using a variable declared a superclass type. Often this is used in conjunction with the base class only providing an abstract method for the subclasses to override.
A trivial example in beginner's books usually involves animals or cars:
public abstract class Animal
{
private final String name;
public Animal(String name)
{
this.name = name;
}
public void printName()
{
System.out.println(name);
}
// more animal general stuff followed by:
public abstract void makeSound();
}
public class Dog extends Animal
{
public Dog()
{
super("Dog");
}
#Override
public void makeSound()
{
System.out.println("Woof!");
}
}
List<Animal> aList = new ArrayList<Animal>();
aList.add(new Dog());
aList.add(new Cat());
// etc
for (Animal a : aList)
{
a.printName();
a.makeSound(); // calls each subclasses' "makeSound()"
}
You can't call the Parent's test() unless you instantiate a Parent or call super.test() from within a method in Child.
(I was actually thinking I could find a good duplicate for this that provided a decent answer, but I couldn't)
Simple
Parent parentE = new Parent();
parentE.test();
In case of method overriding that is resolved at run-time based on actual data type of object not on the basis of referee data type.
You can't call call super class's overridden method directly.
Basically, no, you can't do this, and it would be a bad idea. If Child decides that it needs to override one of its inherited methods, then the outside program shouldn't try to subvert that. It's as though the author of the outside module peeked into the implementation of the methods in Parent and Child and decided "I want the Parent version, not the Child version". But that isn't what OOP is all about. The writer of the outside program should not be concerned with how the method is implemented. See Jon Skeet's answer here, which I think explains this as well as anything I've found.
If you find that you really need to do this, then you have a design issue. The solution is going to depend on your particular project (your original code isn't a real-world example so there's no way to answer it for that). But in some cases, the solution might be that the classes need to provide two different methods that have similar but slightly different purposes. And it may be that in some subclasses of your class, the two methods would have the exact same implementation, but in other subclasses they would be different.
I think you mixed two concepts over here. casting and polymorphism. Read about these concept then things will be more clear for you.
I aware that Java object constructors implicitly initialize their instance's non-static fields. However, I'm unsure of the order that this happens in a class hierarchy. For example:
abstract public class AbstractPieceSequence implements PieceSequence
{
private Tetromino current;
private Tetromino preview;
public AbstractPieceSequence()
{
advance();
}
#Override
public final void advance()
{
if (preview == null) {
current = getNextPiece();
preview = getNextPiece();
} else {
current = preview;
preview = getNextPiece();
}
}
abstract protected Tetromino getNextPiece();
}
public class ShufflePieceSequence extends AbstractPieceSequence
{
private List<Shape> bag = new LinkedList<Shape>();
#Override
protected Tetromino getNextPiece()
{
if (bag.size() == 0) {
Collections.addAll(bag, Shape.I, Shape.J, Shape.L, Shape.O, Shape.S, Shape.T, Shape.Z);
}
return Tetromino.tetrominoes.get(bag.remove(0));
}
}
The parent's constructor calls a method in the child class, which throws an exception as the value of List<Shape> bag is currently null.
I can define a child constructor and call super(), but that must be the first line in the constructor body (which means I still don't have a chance to initialize bag before getNextPiece is called).
I am missing something obvious.
That's right. super(), even if you don't add it explicitly, is placed implictly in every constructor. This means that the constructor of ShufflePieceSequence is called first, but the very first thing it does is calling AbstractPieceSequence.
In AbstractPieceSequence you are calling a method defined in ShufflePieceSequence - which has not been initialized. In fact what you are doing is actually a very subtle bug. You should never call overridable (including abstract methods) from constructor. Period. AFAIR tools like pmd and findbugs are marking this as a potential bug.
See also
What's wrong with overridable method calls in constructors?
Use Care When Calling Non-final Methods from Constructors
Ensure that constructors do not call overridable methods
Object fields are not implicitly initialized... you need to do the init. Maybe you need a lazy init in this case? Generally unpleasant to have the constructor calling methods that do non-trivial work, it's usually a smell that something is more complex than it wants to be.
Depth first, a pre-order walk.
Anders makes a good point: Java only initializes fields that are native types implicitly. Any Object field is merely a reference to Object, and so it in fact initialized, but it's initialized to null.
The order of invoking the constructors of Parent-Sub class in case of inheritance is that, the constructor of Parent class always gets invoke first and then the constructor of Child class.
The Sub class calls the constructor of the base class by default using the Super(), if explicitly not given.
This problem just bit me, its pretty easy to forget to call super() when overriding a method.
In my case I was refactoring some existing stuff where there were already about ten classes overriding a method. Until yesterday the method had an empty default implementation, so it didn't matter if subclasses called super or not.
You can find the overriders just fine with any IDE worth its salt, but you know how it is, phone rings, colleagues have a smalltalk behind you back... its easy to forget to check a place or otherwise overlook it.
Ideally there would be a counterpart for the #Override annotation and the compiler would generate a warning for those places if the base class method is annotated but the override doesnt call super.
Whats the next best thing I can do?
Not quite elegant, but possible solution is to break that method into two:
public abstract class Foo {
public void doBar() {
// do your super logic
doBarInternal();
}
public abstract void doBarInternal();
}
If the superclass implementation MUST ALWAYS be called you could use the 'template method' pattern.
So what you have now is something like:
public static class Parent {
public void doSomething() {
System.out.println("Parent doing something");
}
}
public static class Child extends Parent {
public void doSomething() {
// MUST NOT FORGET SUPER CALL
super.doSomething();
System.out.println("Child doing something");
}
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
And this would become:
public abstract static class Parent {
public final void doSomething() {
System.out.println("Parent doing something");
childDoSomething();
}
public abstract void childDoSomething();
}
public static class Child extends Parent {
public void childDoSomething() {
System.out.println("Child doing something");
}
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
(classes are made static for easy testing within one class)
I made doSomething final to avoid it being overridden since in this solution childDoSomething should be implemented instead.
Of course this solution means Parent can no longer be used as a concrete class.
EDIT: after reading comments about Child implementing a third party interface; this does not need to be a problem:
public interface ThirdPartyInterface {
public void doSomething();
}
public abstract static class Parent {
public final void doSomething() {
System.out.println("Parent doing something");
childDoSomething();
}
public abstract void childDoSomething();
}
public static class Child extends Parent implements ThirdPartyInterface{
public void childDoSomething() {
System.out.println("Child doing something");
}
// public final void doSomething() {
// // cannot do this because Parent makes it final
// }
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
Loooking for something else I found interesting OverrideMustInvoke annotation in FindBugs:
http://findbugs.sourceforge.net/api/edu/umd/cs/findbugs/annotations/OverrideMustInvoke.html
If you do not insist on compile time safety you could use a mechanism that throws an exception whenever a subclass does not behave as logically required: How do I force a polymorphic call to the super method?
I have 2 different suggestions:
1) Build a junit test that discovers all subclasses of your base class, and then selects all the methods decorated with the #Override annotations. I have some unit tests that do something similar (i.e. find all subclasses, check that they truly are Serializable for example).
Unfortunately, the verification of whether they call "super" is a little less straightforward. You would either need to have the test look up the source file, and search it, or better (but I don't know how to do this), read the byte code and see if you can detect the call to super.
2) Needing to guarantee a call to super is probably an indicator of a design/interface issue, rather than a coding/implementation issue. If you really want to guarantee that users call super, it would be better to make the super class abstract, clearly designate an abstract implementation method for them to override, and have the super control the flow of execution.
If you want to define a default implementation, so that not all users need to subclass provide implement that method, you could define a default implementation class for people to use. (And if you really want to control it, define that default class implementation method as final to force them to go back to subclassing the abstract parent.)
Code reuse inheritance is always harder to manage, and so it needs to be done carefully. Anyone doing code reuse inheritance has to have a good idea of the internals of the super class to do it right (which is a bit yucky). For example, do you have to call super.method() at the beginning of your overriding code, or at the end? (or could you do it in the middle...)
So in summary, the best solution is to try avoid a design where you have to enforce that.
What could work - creating some marker annotation (i.e. #MustCallParent) and then create some annotation processor to check that methods marked with it comply to the constraint.