Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling super method from within an anonymous inner class inside the overridden method

Tags:

Imagine we have a class:

class A {
  public void m() {
     System.out.println("A - > m()");
  }
}

...and I want to override the method m on class creation without making a second subclass B to extend A.

public static void main(String[] args) {
    A a = new A() {
        @Override
        public void m() {
            System.out.println("Override - > m()");
            new Thread(new Runnable() {
                @Override
                public void run() {
                   // I want to be able to call the super method.
                   // This is illegal!
                   A.super.m();
                }
            }).start();
        }
    };
    a.m();
}

Currently my solution is to create a private method that calls the super.m()

   A a = new A() {

        private void superMethod() {
            super.m();
        }

        @Override
        public void m() {
            System.out.println("Overrided - > m()");
            new Thread(new Runnable() {

                @Override
                public void run() {
                    superMethod();
                }
            }).start();
        }
    };
    a.m();

I want to know why I am not able to write A.super.m() and if there another way to perform this task.

like image 517
kirilv Avatar asked Jan 26 '15 10:01

kirilv


2 Answers

I want to know why I am not able to write A.super.m()...

This is because A is in fact not a directly enclosing class. The directly enclosing class of the Runnable is new A() { ... } which is an anonymous subclass of A.

In other words, if you would have had

class A extends Base {
    new Runnable() { ... }
}

then A.super would have worked, but now you have

class <Anonymous subclass of A> extends A {
    new Runnable() { ... }
}

which means that something like A.super isn't possible, since there's no syntax for <Anonymous subclass of A>.super.m.

...and, is there another way to perform this task.

The way you've solved it is reasonable in my opinion. Another way would be to create a local subclass of A (just to introduce an identifier to use in ____.super.m) as follows:

public static void main(String[] args) {

    class SubA extends A {
        @Override
        public void m() {
            System.out.println("Override - > m()");
            new Thread(new Runnable() {

                @Override
                public void run() {
                    SubA.super.m();
                 // ^^^^ we now have a name of the directly enclosing class
                }
            }).start();
        }
    }
    A a = new SubA();
    a.m();
}
like image 175
aioobe Avatar answered Sep 21 '22 15:09

aioobe


Writing A.super.m(), suppose that A has a superclass with a m method. But in your code, you don't specify a superclass, and by default, the only superclass you have is Object.
But Object class doesn't have a 'm' method, so you could not call it. A good way to do something like that is to use design pattern, like decorator.

like image 38
vincent Avatar answered Sep 20 '22 15:09

vincent