4

I searched for this but unfortunately failed to find matches, I have this local anonymous inner class inside a method like this:-

new Object(){
    public void open(){
        // do some stuff
    }
    public void dis(){
        // do some stuff
    }
};

with 2 methods inside it (open,dis) and I know that if I want to use anyone of them just do

new Object(){
    public void open(){
        // do some stuff
    }
    public void dis(){
        // do some stuff
    }
}.open()

Now my question is What if I want to call the two methods at the same time How can I do this ?

Scorpion
  • 577
  • 4
  • 21
  • 1
    One way could be to have `open` return `this`, and chain the calls. – njzk2 Mar 04 '14 at 22:37
  • @njzk2 I thought about this. But in this case what type should `open` return? – Andrei Nicusan Mar 04 '14 at 22:40
  • This has a strong "code smell". If you need to invoke both methods the only way to do it is returning `this` and chaining, but that commandeers the return mechanism and perverts any natural return type for non-setter methods. If you need to invoke both methods you need a real class. – Jim Garrison Mar 04 '14 at 22:43
  • @Scorpion There is a good example in The Java Tutorials http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html – Brian Mar 04 '14 at 22:46
  • What about calling dis() inside open() ? Won't that do the trick ? – Evdzhan Mustafa Mar 04 '14 at 22:49
  • 1
    Do you mean really "at the same time" or "on the same instance"? – robermann Mar 04 '14 at 22:54

3 Answers3

6

You may create an interface like this:

interface MyAnonymous {
   MyAnonymous open();
   MyAnonymous dis();  //or even void here
}

new MyAnonymous(){
    public MyAnonymous open(){
        // do some stuff
        return this;
    }
    public MyAnonymous dis(){
        // do some stuff
        return this;
    }
}.open().dis();

EDIT ----

As @Jeff points out, the interface is needed only if the reference is assigned. Indeed, the following solution (evoked by @JamesB) is totally valid:

new MyObject(){
        public MyObject open(){
            // do some stuff
            return this;
        }
        public MyObject dis(){
            // do some stuff
            return this;
        }
    }.open().dis();

but this would not compile:

MyObject myObject = new MyObject(){
            public MyObject open(){
                // do some stuff
                return this;
            }
            public MyObject dis(){
                // do some stuff
                return this;
            }
        };
myObject.open().dis();  //not compiling since anonymous class creates a subclass of the class
Mik378
  • 21,881
  • 15
  • 82
  • 180
  • @Jim Thanks for the immediate editing ;) I missed the most important ;) – Mik378 Mar 04 '14 at 22:41
  • You don't even really need the `interface`, honestly. And if you have the `interface`, there's no need to chain the method calls at all or call them right after instantiation of the object, thanks to polymorphism. You don't have to have the methods return itself. – asteri Mar 04 '14 at 22:45
  • @Jeff I don't strictly need an interface, but the OP does not provide a complete context to confirm that I can bypass it. By the way, disagree concerning your second thing: chaining has nothing to do with concept of `polymorphism`, it's just a way of having a concise code, useful in some cases: http://en.wikipedia.org/wiki/Fluent_interface. – Mik378 Mar 04 '14 at 22:48
  • I never claimed that chaining had to do with polymorphism. I'm claiming that thanks to polymorphism, there's no reason to have the methods chain. You can simply declare a variable `MyAnonymous object = new MyAnonymous() { /* method implementations here */ };` then call `object.open();` and `object.dis();` separately. – asteri Mar 04 '14 at 22:50
  • @Jeff yes, but Fluent Interface would allow to transform those two lines of calls in one. Useful for the Builder pattern by Joshua Bloch for example. Explanation here: http://stackoverflow.com/a/4342728/985949 – Mik378 Mar 04 '14 at 22:51
  • I would strongly advise to use the @Override annotation to clearly indicate that you are implementing methods from the interface – njzk2 Mar 05 '14 at 14:05
1
new MyObject(){
    public MyObject open(){ 
        // do some stuff
        return this;
    }
     public MyObject dis(){ 
        // do some stuff 
        return this;
    }
}.open().dis();
JamesB
  • 7,774
  • 2
  • 22
  • 21
  • "MyObject cannot be resolved to a type." This is not the complete answer. – exception1 Mar 04 '14 at 22:43
  • @exception1 You have to actually have a class called `MyObject` somewhere. It would've compiled for you if the example just used `Object`. – asteri Mar 04 '14 at 22:44
  • 2
    Your answer assumes that `MyObject` exists and already defines (above) those methods. – Mik378 Mar 04 '14 at 22:44
  • @Mik378 You're wrong that the `MyObject` has to already define those methods. That's the whole point of an anonymous class. You're thinking of overriding, which is a different matter/point. – asteri Mar 04 '14 at 22:48
  • @Jeff An anonymous ADDING some methods (no polymorphism), subclasses in reality the concerned class. Thus, `MyObject` would not be aware of those methods. Explanation here: http://www.beingjavaguys.com/2013/10/what-is-anonymous-class-in-java.html (part of "Creating a anonymous inner class using a class’s reference variable.") If I was overriding on the contrary, this would compile ;) – Mik378 Mar 04 '14 at 22:57
  • @Mik378 Which is exactly what the OP does in his question. `MyObject` isn't aware of `open()` or `dis()`, just as `Object` isn't. The implementation in your question *also* makes an anonymous subclass of `MyAnonymous`, and in both cases, the `is-a` relationship between the anonymous subclass and the parent class is identical. I'm not sure what you think the significant difference between your two solutions is, especially since you chain directly after the instantiation of the object, just as James does, and don't take advantage of polymorphism. This is a correct answer to the question. +1 – asteri Mar 04 '14 at 23:03
  • @Jeff Indeed Jeff, you're totally right ;) I read too quickly the answer! That would be applicable only the method calls was not on the same line than the creation. – Mik378 Mar 04 '14 at 23:07
  • @Jeff Updated my given answer. – Mik378 Mar 04 '14 at 23:11
  • @Mik378 I gotcha. It's all good, I +1'd yours, too. Haha. Both are right. – asteri Mar 04 '14 at 23:13
  • @Jeff Being perfectionist by nature, I prefer yours, since more close to the OP specific case :) – Mik378 Mar 04 '14 at 23:14
1

If you want to call methods from an anonymous class, that means it extends a superclass or implements an interface. So you can simply store in a parent's reference that instance and call on it all the contract's methods:

interface MyAnonymous {
   void open();
   void dis();
}

MyAnonymous anon = new MyAnonymous () {
    public void open(){
        // do some stuff
    }
    public void dis(){
        // do some stuff
    }
};

anon.open();
anon.dis();
robermann
  • 1,722
  • 10
  • 19