Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is super.super.method(); not allowed in Java?

I read this question and thought that would easily be solved (not that it isn't solvable without) if one could write:

@Override public String toString() {     return super.super.toString(); } 

I'm not sure if it is useful in many cases, but I wonder why it isn't and if something like this exists in other languages.

What do you guys think?

EDIT: To clarify: yes I know, that's impossible in Java and I don't really miss it. This is nothing I expected to work and was surprised getting a compiler error. I just had the idea and like to discuss it.

like image 411
Tim Büthe Avatar asked Feb 25 '09 15:02

Tim Büthe


People also ask

Is super super allowed in Java?

Your code would break if you called a super of a super that had no super. Object oriented programming (which Java is) is all about objects, not functions. If you want task oriented programming, choose C++ or something else.

What are the conditions for using super () method?

We can use super keyword to access the data member or field of parent class. It is used if parent class and child class have same fields. In the above example, Animal and Dog both classes have a common property color. If we print color property, it will print the color of current class by default.

What are the conditions for using super () method in Java?

Call to super() must be first statement in Derived(Student) Class constructor. If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass.

Is super () necessary Java?

However, using super() is not compulsory. Even if super() is not used in the subclass constructor, the compiler implicitly calls the default constructor of the superclass.


2 Answers

It violates encapsulation. You shouldn't be able to bypass the parent class's behaviour. It makes sense to sometimes be able to bypass your own class's behaviour (particularly from within the same method) but not your parent's. For example, suppose we have a base "collection of items", a subclass representing "a collection of red items" and a subclass of that representing "a collection of big red items". It makes sense to have:

public class Items {     public void add(Item item) { ... } }  public class RedItems extends Items {     @Override     public void add(Item item)     {         if (!item.isRed())         {             throw new NotRedItemException();         }         super.add(item);     } }  public class BigRedItems extends RedItems {     @Override     public void add(Item item)     {         if (!item.isBig())         {             throw new NotBigItemException();         }         super.add(item);     } } 

That's fine - RedItems can always be confident that the items it contains are all red. Now suppose we were able to call super.super.add():

public class NaughtyItems extends RedItems {     @Override     public void add(Item item)     {         // I don't care if it's red or not. Take that, RedItems!         super.super.add(item);     } } 

Now we could add whatever we like, and the invariant in RedItems is broken.

Does that make sense?

like image 140
Jon Skeet Avatar answered Oct 16 '22 22:10

Jon Skeet


I think Jon Skeet has the correct answer. I'd just like to add that you can access shadowed variables from superclasses of superclasses by casting this:

interface I { int x = 0; } class T1 implements I { int x = 1; } class T2 extends T1 { int x = 2; } class T3 extends T2 {         int x = 3;         void test() {                 System.out.println("x=\t\t"          + x);                 System.out.println("super.x=\t\t"    + super.x);                 System.out.println("((T2)this).x=\t" + ((T2)this).x);                 System.out.println("((T1)this).x=\t" + ((T1)this).x);                 System.out.println("((I)this).x=\t"  + ((I)this).x);         } }  class Test {         public static void main(String[] args) {                 new T3().test();         } } 

which produces the output:

 x=              3 super.x=        2 ((T2)this).x=   2 ((T1)this).x=   1 ((I)this).x=    0 

(example from the JLS)

However, this doesn't work for method calls because method calls are determined based on the runtime type of the object.

like image 30
Michael Myers Avatar answered Oct 16 '22 21:10

Michael Myers