Today I realized that calling super.foo() is possible not only inside an overriding foo method, but also inside completely unrelated methods:
class Base
{
void foo()
{
}
}
class Derived extends Base
{
void foo()
{
}
void bar()
{
super.foo();
}
}
Is there any real-world scenario, Design Pattern or whatever where this is actually useful?
This would be helpful when a child class wants to provide more meaningful names to a method than the parent class, or providing additional information about the operation in the method name.
Related
Class Base{
public void doThings(){
//some logic that needed by subclass
}
}
Class A extends Base{
public void doThings(){
super.doThings();
doOtherThings();
}
}
What I want is to force A to overwrite doThings() method(there will be error message if not) and call super.doThings(); but doThings() in Base should not be abstract for it has body.
Is there any decent solutions? I found the same question in below link but the accepted answer does not answer it right.
Force SubClasses to #Override method from SuperClass. Method in SuperClass must have body
If you want to make sure that doThings of the base class is called, you should design your class like this:
abstract class Base {
public void doThings() {
// do some things here
...
// make sure subclass does some things too
methodYouMustImplement();
}
abstract void methodYouMustImplement();
}
class A extends Base {
#Override void methodYouMustImplement() {
// do some other things
}
}
This way, A is forced to give a implementation of methodYouMustImplement() and it is guaranteed by design that your code in doThings() is called without the need to remember to call super.doThings().
You could then consider making doThings() final, as Andy Turner suggested.
I think it would be easier to use a construct such as:
public class Base {
public void doStuff() {
doSpecificStuff();
// do base stuff every one has to do
}
abstract void doSpecificStuff();
}
public class WeirdlySpecific extends Base {
public void doSpecificStuff() {
// specific stuff happens
}
}
This does not force WeirdlySpecific to actually implement the doStuff() method, but as long as doStuff() is called as a contract by any caller, each more specific implementation has its own version of events.
A requirement to call the super method is considered an anti-pattern; that aside, the only way you can force a subclass to implement a method is to make it abstract.
If you want super.doThings() to be called first, and then subclass-specific stuff to be run after, turn the problem around:
Make doThings() final
Add an abstract method that is called within doThings().
Something like this:
abstract class Base {
public final void doThings() {
methodYouMustImplement();
// Stuff after subclass-specific implementation.
}
abstract void methodYouMustImplement();
}
class A extends Base {
#Override void methodYouMustImplement() {
doOtherThings();
}
}
The fact that doThings() is final is important to the requirements: this guarantees that the things you want to happen when doThings() is invoked, because no subclass can change this method. If you leave it non-final, subclasses can decide to override doThings(), meaning that methodYouMustImplement() (and any other actions you specify in doThing()) are not necessarily called.
For example, I have many classes that all need a certain method.
In this method, all these classes need one line of code, the remainder of the method is different.
How could I achieve something like this:
void method(){
everybodyDoesThisStuff;
// more individual stuff
// more individual stuff
}
Abstract methods cannot have a body, and if you were not to make it abstract you would then override the method and lose it.
You should make the method that does the "more individual stuff" abstract, not the method itself.
// AbstractBase.java
public abstract class AbstractBase {
public final void method() {
everybodyDoesThisStuff();
doIndividualStuff();
}
abstract void doIndividualStuff();
private void everybodyDoesThisStuff() {
// stuff that everybody does
}
}
// ConcreteClass.java
public class ConcreteClass extends AbstractBase {
void doIndividualStuff() {
// do my individual stuff
}
}
One solution is to require all subclasses to call super.method(). The problem is that there's no way to actually enforce that. Another option is to create a separate method that internally executes the required line and then calls an abstract method:
public final void method() {
callEveryTime();
doMethod();
}
protected abstract void doMethod();
Note that method() is public final so it can be called anywhere but not overridden, whereas doMethod() is protected so it can be overridden but not called outside its package (or subclasses).
You can make a normal method call an abstract method:
void foo(){
// do stuff
bar(); // let the abstract method do the rest
}
abstract void bar();
If you're asking yourself whether you need partial implementations of an abstract method, it's usually time to reconsider the granularity of your design.
Why not extract everybodyDoesThisStuff into a separate method and put it in an Interface?
Java 8 introduces the concept of default methods. Consider the following interface with a default method :
public interface IDefaultMethod {
public abstract void musImplementThisMethod();
public default void mayOrMayNotImplementThisMethod() {
System.out.println(" This method is optional for classes that implement this interface ");
}
}
And a class that implements this interface :
public class DefaultMethodImpl implements IDefaultMethod {
#Override
public void musImplementThisMethod() {
System.out.println("This method must be implementd ");
}
#Override
public void mayOrMayNotImplementThisMethod() {
// TODO Auto-generated method stub
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
}
}
I have a question about the readability of the following call in the mayOrMayNotImplementThisMethod :
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
I understand that the reason for explicitly specifying the interface name in the above call is to avoid confusion in case multiple interfaces implemented by the class have the same method. What I don't understand is the meaning of the super keyword in this context. When we say IDefaultMethod.super, what exactly are we referring to here? Wouldn't IDefaultMethod.mayOrMayNotImplementThisMethod() be more readable than IDefaultMethod.super.mayOrMayNotImplementThisMethod()? Removing the super keyword makes it more readable at the cost of distinguishing between a static or non static method call.
I will try to contribute to the discussion by following my own reasonings about this.
Using Classes
First, let's see how this work with simple Java classes:
class Barney {
void foo() { System.out.println("Barney says foo"); }
}
class Fred extends Barney {
#Override void foo() { super.foo(); }
}
In this case if we invoke the method foo in a Fred instance it will ask for the implementation of the foo method in its super class and execute that one.
Evidently, none of these others would work:
#Override void foo() { foo(); } //means this.foo() so infinite recursion
#Override void foo() { Barney.foo(); } //means a static method
There is a third configuration that we could do:
class Barney {
void foo() { System.out.println("Barney says foo"); }
class Fred extends Barney {
#Override void foo() { Barney.this.foo(); }
}
}
In this case if we invoke foo in a instance of Fred, since this instance would have a bond with its enclosing instance, this invocation would invoke the foo method in the enclosing instance of Barney.
For instance
new Barney().new Fred().foo();
So, the use of Barney.this here is used to navigate between instances in an inner/outer relation.
Using Interfaces
Now let's try to repeat the same ideas with interfaces.
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
}
interface Fred extends Barney {
#Override default void foo() { Barney.super.foo(); }
}
As far as I can tell, this is exactly the same thing as with classes, it is just that in this case since an interface can inherit from more than one interface we simply qualify the super keyword with the name of the interface we are targeting in this case.
The meaning is the same, we want to invoke the "implementation" of the foo method in the super interface explicitly named.
As with classes, the following would not work:
#Override default void foo() { super.foo(); } //can't be sure of which interface
#Override default void foo() { this.foo(); } //infinite recursion
#Override default void foo() { Barney.foo(); } //static method
#Override default void foo() { Barney.this.foo(); } //not an inner class relation
So, the logical choice here is Interface.super.method().
A question here would be whether we cab ever have a use case like Interface.this.method when using interfaces.
Not really, because interfaces represent a static context, therefore there is never a concept like that of inner classes between interfaces. So this is never possible.
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
interface Fred extends Barney {
#Override default void foo() { Barney.this.foo(); }
}
}
Basically, this is not possible because the code above does not mean that an instance of Fred would need to exist within the context of an instance of Barney. This is just a static inner interface and instances of it can exist independently of any instances of the parent interface.
So, that's why this would not be a good choice.
So, as you can see, after all this the use of super kind of makes sense, or at least I hope I have explained myself well enough to convey that idea.
This is simply an extension to default methods of the usual approach to accessing members of superclasses (JLS 15.11):
The form T.super.Identifier refers to the field named Identifier of the lexically enclosing instance corresponding to T, but with that instance viewed as an instance of the superclass of T.
Essentially, there can be ambiguity about which member is being referred to when a class has more than one ancestor (whether because of default methods or just because it has multiple superclasses in a hierarchy). The super keyword is the analog of Outer.this in an inner class; it means that you want to get "this, but the stuff I would see inside the body of that superclass instead of the member inside this subclass".
super refers to a class or interface you inherit from. It is means you want to call a method ignoring the fact it has been overridden.
If you used this you would be referring to this class (or a sub-class) and thus have infinite recursion.
Java 8 interfaces also have static methods.
If you say,
IDefaultMethod.mayOrMayNotImplementThisMethod();
Then it is a way to call static method, which also seems correct as it is similar to how we access static members of class.
For default method, if 'super' is not used then they might have used 'this', which does not make sense as 'this' belongs to class where we are making method call.
My opinion is, you are correct as it does not provide good readability but seems it is as per language design.
Let's say I have a method called mymethod()
and this method overrides the method of the super class method.
What does it mean to override a method?
Does that mean mymethod() ignores everything that is in the method of the superclass, or does that means mymethod() also includes everything in the superclass method?
When overriding a method, can I only override the methods of the same name, or I can override methods of any name?
thanks.
An example:
public class Base {
public void saySomething() {
System.out.println("Hi, I'm a base class");
}
}
public class Child extends Base {
#Override
public void saySomething() {
System.out.println("Hi, I'm a child class");
}
}
Now assume we have a main function somewhere...
public static void main(String [] args) {
Base obj = new Child();
obj.saySomething();
}
When this runs, it will call Child's version of saySomething, because you overrode the parent's version by giving a new version of the function in Child.
The #Override annotation allows other developers (and you, when you forget) to know that this method overrides something in a base class/interface, and it also allows the compiler to yell at you if you're not actually overriding anything in a base class. For example, if you got the number of arguments wrong for a function, the compiler will give you an error saying your #Override is incorrect.
For example:
public class Child extends Base {
#Override
public void saySomething(int x) {
System.out.println("I'm a child and x is: " + x);
}
}
The compiler will yell at you because this version of saySomething takes an argument, but the parent's version doesn't have an argument, so you're #Override-ing something that's not in the parent.
On super
The Child version of saySomething will not invoke the Base version, you have to do it yourself with super.method().
For example:
public class Child extends Base {
#Override
public void saySomething() {
super.saySomething();
System.out.println("I'm also a child");
}
}
If you ran the main and used this Child class, it would print out I'm a base and I'm also a child.
Overriding means that when you call a method on your object, your object's method is called instead of the super class. The #Override annotation is something you use to make sure that you are overriding the correct method of the superclass. If you annotate a method that does not exist in the superclass, the Java compiler will give you an error. This way you can be sure that you are overriding the correct methods. This is especially useful in cases like this:
public class MyClass {
...
public boolean equals(MyClass myClass) {
...
}
}
There is a logic-bug in the code above. You haven't actually overridden the Object class's equals method. If you add the #Override annotation:
public class MyClass {
...
#Override
public boolean equals(MyClass myClass) {
...
}
}
The Java compiler will now complain because there is no corresponding method in the parent class. You'll then know that the correct solution is:
public class MyClass {
...
#Override
public boolean equals(Object o) {
...
}
}
To call the parent class's method, you can call super.overriddenMethod() where overriddenMethod is the name of the method you have overridden. So if you want to do something in addition to what the parent class already does, you can do something like this:
public class MyClass {
...
#Override
public void overriddenMethod() {
super.overriddenMethod();
/* whatever additional stuff you want to do */
}
}
If an inheriting class has on override method of the same name as the parent class it will be called instead of the one in the parent class. This only works if the names are the same, and of course if the signature of the method matches your call to the method.
What does it mean to override a method?
It means you replace the super class definition of the method with your own definition.
does that mean mymethod() ignores everything that is in the method of the super class?
or does that means mymethod() also includes everything in the superclass method?
You can choose whether to include the super class definition within your definition. To include it, you need to call super.mymethod() within mymethod().
and when overriding a method, can I only override the methods of the same name, or I can override methods of any name?
To override a method, you must supply a method in the sub class with the same signature (which means the same name, parameters and return type).
As a side note, the #Override annotation in your question does not actually cause your method to override another method. It causes a compile-time error if a method annotated with it does not have a signature matching a public or protected method of a super class (or interface as of 1.6).
I once had a student come to ask me why his code wasn't working. He had spent several days wondering why he could put something into a collection but was not able to find it. His code was something like:
public int hashcode()
instead of:
public int hashCode()
So the hashCode method never got called.
Adding #Overrides to a method makes it clear that you are overriding the method AND make sure that you really are overriding a method.
When you override a method of the super class, calling that method on your object calls its method instead of that of the super class.
You can call the super class's method (despite having overridden it) using super.methodName(). A common reason for this is when the overridden method would otherwise reimplement the super class method and add additional code specific to the extending class (public void methodName() { super.methodName(); /* more code */ }).
#Override annotation allows you to cause warning at compile time if the method isn't actually overriding anything. It isn't necessary, but these warning are a hit to you that you might have got the signature wrong in the extending class, forgot to implement the method at all in the super class, or some other silly mistake.
This question already has answers here:
Closed 13 years ago.
Part of me thinks that this shouldn't be possible (even if it is), but I'll ask anyway.
Given the following class hierarchy (Grandparent and Parent are from a 3rd party and thus, not under my control), how would I override myMethod() in Child such that it bypasses the overridden implementation in Parent and invokes the one in Grandparent?
class Grandparent {
public void myMethod() {
// do stuff
}
}
class Parent extends Grandparent {
#Override public void myMethod() {
super.myMethod();
// do something else
}
}
class Child extends Parent {
#Override public void myMethod() {
// ??? I want to *only* do what Grandparent did here
}
}
Pretend that the Parent class provides a lot of other helpful behavior and is a crucial element of Child's hierarchy (in other words, I'm not looking for "make Child a subclass of Grandparent".
The idea behind inheritance is that each class defines their methods how they need, so you don't need to be inspecting any code.
It seems like you're subclassing here just to re-use code, and that's not the idea of subclassing.
Maybe you should have a helper member to do some of the tasks you need, instead of subclassing, and have both "Child" and "Parent" classes extend "Grandparent".
The main question you need to ask yourself is: "Is Child really a descendant of Parent, Grandparent or neiter?" In other words, for every instance of Child, can I say it's a Parent?
If the answer is no, then you're subclassing wrongly: inheritance is supposed to mean something, not just code re-use (i.e. Ford IS ALSO a Car, not just "Ford" uses "Car" methods).
Assuming that I couldn't touch the code in Parent or Grandparent and assuming that I'm not, as Seb suggested (and as Steve apparently agreed) simply misusing inheritance entirely:
I'd create a local instance of a Grandfather object (or a local class extending Grandfather, if it's abstract) and access its interpretation of myMethod() directly. Of course, depending on how much state information myMethod() is supposed to read and/or manipulate, the amount of work involved could be anything from "easy" to "excruciating".
It's an ugly solution, and, depending on how much state information is accessed, could be brittle as hell. But if Grandfather is reliably stable and/or myMethod() is fairly self-contained, it could work. The devil is in the details, as always.
I definitely agree with Seb that this is re-use, not inheritance. But, hey. Re-use is often a Good Thing.
Not possible.
I would create a final helper method in grandparent instead. And have this method (which is overridden) call that helper.
class Grandparent {
public final void myHelperMethod() {
// do stuff
}
public void myMethod() {
myHelperMethod();
}
}
class Parent extends Grandparent {
#Override public void myMethod() {
super.myMethod();
// do something else
}
}
class Child extends Parent {
#Override public void myMethod() {
// ??? I want to *only* do what Grandparent did here
myHelperMethod();
}
}
Do you have control of the Parent class?
If so, could you add a method (myNewMethod) to the Parent that calls myMethod on Grandparent, and call myNewMethod from Child?
(I'm not a Java person, so don't know if you can only call a method in a superclass from an override of that method in a subclass)
class Grandparent {
public void myMethod() {
myHelperMethod();
}
}
class Parent extends Grandparent {
#Override public void myMethod() {
super.myMethod();
// do something else
}
public final void myNewMethod() {
super.myMethod();
}
}
class Child extends Parent {
#Override public void myMethod() {
// ??? I want to *only* do what Grandparent did here
myNewMethod();
}
}