Java: Generics and inheritance - java

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>

Related

Cast classes to classes with generics

I am reflectively getting classes and their declared classes, and I want to pass them into a function that takes classes, but it has generics on it.
// classes to pass into function
ClassPath.from(MyParent.class.getClassLoader())
.getTopLevelClasses()
.forEach(classInfo -> {
// checks...
Class<?> clazz = classInfo.load();
for (Class<?> declaredClass : clazz.getDeclaredClasses()) {
genericFunction(clazz, declaredClass); // the problem
}
});
// the function to pass into
<E extends Extendable<? extends Parent<E>>> void genericFunction(Class<? extends Parent<E>> parentClass, Extendable<E> extendableClass);
// classes used in generic function
public class MyParent extends Parent<MyExtendable> {
protected class MyExtendable extends Extendable<MyParent> {
}
}
public abstract class Parent<E extends Extendable<? extends Parent<E>>> {
}
public abstract class Extendable<E extends Parent<? extends Extendable<E>>> {
}
The problem is that I have no idea how to cast or reflective run that genericFunction() with the Class<?> objects.
I can assume that the classes that ClassPath finds are compatible (e.g: they all properly extend Parent and Extendable in inner classes.)
I can change my (likely) messy and overcomplicated generics on the function and classes.

Java generics in pipeline architecture

I have a base abstract class PipelineStage which has the following definition:
public abstract class PipelineStage<I, O> implements Runnable {
...
public abstract O step(I input);
...
}
I then have numerous concrete pipeline stages with definitions such as:
public class ConcreteStage extends PipelineStage<InputContextClass, OutputContextClass> {
...
#Override
public OutputContextClass step(InputContextClass input) {
input.someMethod();
...
return new OutputContextClass();
}
...
}
However, this has led to a rigid design in which either:
The context classes are very tightly coupled to which stages they are used in.
Every stage needs to have two full interfaces defined, defining all the properties of the input and output classes.
I wanted to improve this design by having generic interfaces that specify properties of the context classes, the ConcreteStage would then specify what interfaces it's input and output context classes must extend.
However, I can't figure out how to do this in a way the compiler likes.
For example:
public class ConcreteStage extends PipelineStage<I extends Interface1 & Interface2,
O extends Interface2 & Interface3> {
...
#Override
public O step(I input) {
input.someMethodFromInterface1();
input.someMethodFromInterface2();
...
// OutputContextClass extends Interface2 & Interface3
return new OutputContextClass();
}
...
}
However, this doesn't compile, showing that class I needs to be imported.
A wildcard also doesn't work, saying No wildcard expected.
Does anyone have any suggestions on how to implement this in a neat, flexible way? Many thanks in advance!
You need to put the type variable declarations on the class, not the superclass:
public static class ConcreteStage<
I extends Interface1 & Interface2, O extends Interface2 & Interface3>
extends PipelineStage<I, O> {
You can also make an interface uniting input interfaces together interface InputInterface12 extends InputInterface1, InputInterface2 {} and then class ConcreteStage extends PipelineStage<InputInterface12, OutputInterface12> {...}.

Using static nested class as generic parameter

I'm trying to create an interface with a bounded type parameter, with implementations supplying static nested classes to implement this parameter, as follows:
public interface InterfaceProblem<T extends IMyParameter>{
T getParameterInstance();
}
interface IMyParameter {}
class MyClass implements InterfaceProblem<MyParameter> {
public MyParameter getParameterInstance() {
return new MyParameter();
}
class MyParameter implements IMyParameter{}
}
This gives me a compile error "MyParameter cannot be resolved to a type" on the MyClass declaration and its method. This disappears if I move the static class to its own type:
class MyClass implements InterfaceProblem<MyParameter> {
public MyParameter getParameterInstance() {
return new MyParameter();
}
}
class MyParameter implements IMyParameter{}
However, I'd like to avoid that, since the MyParameter implementation is closely related to the MyClass implementation. Is there a better way I can acheive this? Is this correct compiler behaviour? (I'm using Eclipse Mars and Oracle jdk1.8.0_60)
You're missing an import:
import com.example.MyClass.MyParameter;
While the MyParameter type is on scope for the getParameterInstance() method's return type, it is not for the MyClass's binding of <T>

Instantiating anonymous inner classes in Java with additional interface implementation

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();

Is it possible to extend from a template parameter?

I would like to decorate a set of classes that derive from a common class (TextView). The classes exist in a library, so I cannot simply modify the base or insert into their inheritance hierarchy.
class A {
}
class B extends A {
}
class C extends A {
}
class D extends B {
void decoration(){}
}
In the example above, class D is the decorating class. The decorating functionality is common to each of my decorating classes.
My question is, is it possible to template the base class in Java? Something like:
class D<T> extends <T ? extends A> {}
So your question is about adding a method dynamically to existing classes? Something similar to categories in Objective-C. This is not simple to be done in Java since once a class is loaded through the ClassLoader you can't add anything dynamically to it.
The easiest thing that comes into my mind is to provide a custom mapping that will be by any chance external to the existing classes. Something like:
interface Method<T extends A> {
public void invoke(T ref);
}
class MethodForA implements Method<A> {
public void invoke(A ref) { .. }
}
class MethodMapper {
Map<Class<?>, Method<? extends A>> mapping;
MethodMapper() {
mapping = new HashMap<Class<?>, Method<? extends A>>();
mapping.put(A.class, new MethodForA());
}
void invoke(A object) {
Method<? extends A> method = mapping.get(object.getClass());
if (method != null) {
method.invoke(object);
}
}
I just wrote this boilerplate code right now so everything won't be surely correct but the way it would work is this one. I guess you will need to do some runtime type checks to avoid blindly casting things.
If instead you were wondering if this is legal:
class A {
}
class B<T> extends A {
}
class C<T, U> extends B<T> {
}
Yes, it is. You can make a child class generic by introducing a type parameter.

Categories