Instantiating anonymous inner classes in Java with additional interface implementation - java

Let's say I have the following two class/interface definitions:
public abstract class FooClass {
public abstract void doFoo();
}
and
public interface BarInterface {
public void doBar();
}
If I want to make an anonymous inner class that extends/implements both, do I need to do this:
public abstract class BothClass extends FooClass implements BarInterface {}
...
new BothClass() {
public void doFoo() {
System.out.println("Fooooooooo!!!!");
}
public void doBar() {
System.out.println("Baaaaaaaar!!!!");
}
}.doBar();
Or is there a short-cut that allows me to not define BothClass? Something like this, maybe:
new (FooClass implements BarInterface)() {
public void doFoo() {
System.out.println("Fooooooooo!!!!");
}
public void doBar() {
System.out.println("Baaaaaaaar!!!!");
}
}.doBar();
(This idea gives me several errors, none of which are helpful here)

Let's go to the JLS:
An anonymous class declaration is automatically derived from a class
instance creation expression by the Java compiler.
where a class instance creation expression is
ClassInstanceCreationExpression:
new TypeArgumentsopt TypeDeclSpecifier TypeArgumentsOrDiamondopt
( ArgumentListopt ) ClassBodyopt
Primary . new TypeArgumentsopt Identifier TypeArgumentsOrDiamondopt
( ArgumentListopt ) ClassBodyopt
TypeArgumentsOrDiamond:
TypeArguments
<>
ArgumentList:
Expression
ArgumentList , Expression
So, no, the Java language specification does not allow any shortcuts for making your anonymous class implement more interfaces than the type you're sub-typing.
So, to determine the type of the anonymous class
If the class instance creation expression ends in a class body, then
the class being instantiated is an anonymous class. Then:
If T denotes an interface, then an anonymous direct subclass of Object
that implements the interface named by T is declared.
[...]
Let T be the type named by the Identifier and any type arguments. An
anonymous direct subclass of the class named by T is declared. The
body of the subclass is the ClassBody given in the class instance
creation expression.
Your alternative is the way to do it.
You can also use local classes.

An anonymous class
FooClass f = new FooClass() {
public void doFoo() {}
};
is just a convenient shorthand for a local class definition with a generated name
class $anon extends FooClass {
public void doFoo() {}
}
FooClass f = new $anon();
If you want to implement interfaces just write the local class definition explicitly
class LocalFoo extends FooClass implements BarInterface {
// method declarations here
}
LocalFoo lf = new LocalFoo();

Related

Java: Generics and inheritance

I am building a class Bootstrap for bootstrapping other classes that implement Bootstrappable.
// interface that every class must implement that needs to be bootstrapped
class Bootstrappable implements Runnable {
public foo();
}
class MyApp implements Bootstrappable {
public void foo() {}
}
class Bootstrap {
private Bootstrappable instance;
public bootstrap(Class<Bootstrappable> b) {
instance = b.newInstance();
...
}
}
But then I get a compiler error if I try to pass MyApp.class into Bootstrappable.class.
new Bootstrap().bootstrap(MyApp.class);
The method bootstrap(Class Bootstrappable ) in the type Bootstrap is not applicable for the arguments (Class MyApp)
I think is is because inheritance is not for generics. Any way I can handle this?
If you need a class of something that implements Bootstrappable, you should define its type as follows:
Class<? extends Bootstrappable>

Interface extending a class

Let's say that I have an interface, and all classes that implement that interface also extend a certain super class.
public class SuperClass {
public void someMethod() {...}
}
public interface MyInterface {
void someOtherMethod();
}
//many (but not all) sub classes do this
public class SubClass extends SuperClass implements MyInterface {
#Override
public void someOtherMethod() {...}
}
Then if I'm dealing with an object of type MyInterface and I don't know the specific sub class, I have to hold two references to the same object:
MyInterface someObject = ...;
SuperClass someObjectCopy = (SuperClass) someObject; //will never throw ClassCastException
someObjectCopy.someMethod();
someObject.someOtherMethod();
I tried making the interface extend the super class, but it's a compiler error:
public interface MyInterface extends SuperClass {} //compiler error
I also thought of combining the interface and the super class into an abstract class like so:
public abstract class NewSuperClass {
public void someMethod();
public abstract void someOtherMethod();
}
But then i can't have a sub class that doesn't want to implement someOtherMethod().
So is there a way to signify that every class that implements an interface also extends a certain class, or do I have no choice but to carry around two references to the same object?
I think that the only solution you have would be to have a reference to both, but this indicates that you have a design flaw somewhere. The reason I say is because you should think of an interface as something that your implementing classes will always need. For example, a Car and Airplane both need a Drive() interface. A design reconsideration is probably worth your time. However, if you still want to follow that path, you can do the following:
public class ClassA {
public void methodA(){};
}
public abstract class ClassB extends Class A{
public void methodB();
}
After you have the above setup, you can now reference an object that has the two methods by doing the following:
ClassB classB = new ClassB();
classB.methodA();
classB.methodB();
Now you don't actually have to actually use two pointers to the same object.

Why we can create an interface instance variable although Interface can't be instantiated?

I have following Interface declared
public interface MyInterface {
void do_it_now();
}
The I can do
public class MainClass{
public static void main(String[] args) {
MyInterface mainClass = new MyInterface() {
#Override
public void do_it_now() {
}
};
}
}
Now My Question regarding the above code is by definition Interface can't be instantiated
Whey we are allowed have a instance variable Type of Interface in java. What is the meaning of new MyInterface() line.
I want to know whats going on under the hood.
I have also gone through the post quite slimier to my question. but answer is not quite satisfactory to me .
Please don't give negative feedback or block my account if you found my question stupid post comment I will remove it.
Being able to have a variable of an interface type allows you to assign to that variable an instance of any class that implements that interface. Then you can use that variable to execute interface methods of that instance without caring about the specific implementation being used. It makes your code much more general, since you can switch to a different implementation of the interface without changing the code that uses the variable of the interface type.
You are making an "Anonymous Class" in the second code block. This means that it creates a class that implements the interface or class that you write. Its basically a short hand for making a subclass that implements the interface (MyInterface)
I want to know whats going on under the hood.
Consider the code below, assuming the interface MyInterface defined in your question.
Two inner classes are defined; the first class is anonymous (having no name) and the second class is named MyClass. Each of these two classes implements MyInterface.
// declare variable of type MyInterface
MyInterface myVariable;
// assign the variable to an instance of anonymous class that implements MyInterface
myVariable = new MyInterface() {
#Override
public void do_it_now() {
}
};
// define a named class that implements MyInterface
class MyClass implements MyInterface {
#Override
public void do_it_now() {
}
}
// assign the variable to an instance of named class that implements MyInterface
myVariable = new MyClass();
What's going on under the hood is, the java compiler compiles new MyInterface() {...}; into a separate class file with a name like $1.class, just like it compiles MyClass into a separate class file with a name like MyClass$1.class.

No enclosing instance of type ITask is accessible.

I would like to make abstract class which has several inner classes extend it and could create instances of its inner classes via static methods but I get compiler error "No enclosing instance of type ITask is accessible. Must qualify the allocation with an enclosing instance of type ITask (e.g. x.new A() where x is an instance of ITask)."
I've found out that inner classes should be created by instances of outer class but my outer class has abstract method and I can't create instance of it. I made inner classes which extend parent because I wont to control creation of them.
So is there any way how to make my pattern works.
My code:
public abstract class ITask {
public abstract void Execute(Subscriber itm);
static public ITask CreateSendTask(Buffer buffer)
{
return new SendData(buffer);
}
static public ITask CreateSTTask(Ticket sid)
{
return new StartTransmission(sid);
}
static public ITask CreateETTask(Ticket sid)
{
return new EndTransmission(sid);
}
private class SendData extends ITask
{
/// some implemetation...
}
private class StartTransmission extends ITask
{
/// some implemetation...
}
private class EndTransmission extends ITask
{
/// some implemetation...
}
}
The problem is with methods Create(.*)Task.
Thanks!
The inner classes should be made static if they're created from static methods, and thus don't need access to an enclosing ITask.
You should also respect Java naming conventions: methods start with a lower-case letter.

Java compilation failure when using generics parameter in inner class

Please take a look at the code snippet below:
interface IFoo<E>{
void doFoo(E env);
}
class A<E>{
public void doA(E env){}
}
public class Foo<E> implements IFoo<E>{
public A<E> a;
#Override
public void doFoo(E env) {
a.doA(env);
}
private class FooInner<E> implements IFoo<E>{
#Override
public void doFoo(E env) {
a.doA(env);
}
}
}
Eclipse complains inside of private inner class a.doA(env) with the following message.
The method doA(E) in the type A<E> is not applicable for the arguments (E)
It doesn't seem like accessibility issue because non-static inner class have an access to all instance variables of the outter class. It looks like I defined my generics wrong somewhere. Can anyone explain me what I am doing wrong here?
You've used the same generic parameter name for the inner class, so the type E of the inner class is shadowing the E of the outer class.
Remove generic parameter from the inner class, like this:
public class Foo<E> implements IFoo<E>{
...
private class FooInner implements IFoo<E>{ // "E" here is the same "E" from Foo
#Override
public void doFoo(E env) {
a.doA(env);
}
}
}
The type of the enclosing class is part of the type of the inner class. FooInner is already parameterized by E, because it's part of the outer class; the explicit parameterization is redundant and incorrect, because it's actually trying to introduce a new type parameter using the same name as the existing one. Just remove the <E> in private class FooInner<E>, and you're golden.

Categories