Overriding with generics - java

Consider the following abstract class
public abstract class AbstractAssembler {
public abstract <T extends AbstractValue> void transform(T value);
}
and the following extension:
public class MyAssembler extends AbstractAssembler {
#Override
public void transform(MyValue value) {
// ...
}
}
With MyValue
public class MyValue extends AbstractValue {
// ...
}
Eclipse tells me:
The method transform(MyValue) of type MyAssembler must override or implement a supertype method
Why does this not work?

Your transform() method must override the generic abstract transform() method in the super class, i.e. you should have something like:
public class MyAssembler extends AbstractAssembler {
#Override
public <T extends AbstractValue> void transform(T value) {
}
}
If you want to invoke it with an actual type (e.g. MyValue) you should do:
MyValue value = new MyValue();
new MyAssembler().transfer(value);
where explicitly specifying the type-parameter (new MyAssembler().<MyValue>transfer(value);) is optional, as it will be inferred by the compiler.
If you however wish MyAssember's transform method to work only with MyValue, then you should do:
public class MyAssembler extends AbstractAssembler<MyValue> {
#Override
public void transform(MyValue value) {
}
}

Related

How to make a reference to a concrete subtype in an abstract method definition

Suppose I have the following definition:
public abstract class SomeAbstractClass {
public abstract List<SomeAbstractClass> getNextElements() ;
}
If I build a concrete class that extends SomeAbstractClass named for instance SomeConcreteClass I would like getNextElements to have the following signature:
public List<SomeConcreteClass> getNextElements()
Instead of:
public List<SomeAbstractClass> getNextElements()
In other words, I would want my abstract definition to have a type depending on the current concrete type. Can it be done ? If so, how ?
Just use Java generics:
public abstract class SomeAbstractClass<T extends SomeAbstractClass> {
public abstract List<T> getNextElements() ;
}
public class SomeConcreteClass extends SomeAbstractClass<SomeConcreteClass> {
#Override
public List<SomeConcreteClass> getNextElements() {
return new ArrayList<>();
}
}
Another possibility would be to use only generic methods as follows:
public abstract class SomeAbstractClass {
public abstract <T extends SomeAbstractClass> List<T> getNextElements();
}
public class SomeConcreteClass extends SomeAbstractClass {
#Override
public List<SomeConcreteClass> getNextElements() {
return new ArrayList<>();
}
}
The downside of this is that you now have an unchecked conversion at List<SomeConcreteClass> getNextElements() which may potentially trigger ClassCastException at runtime.

What is the reason behind overriding a method/methods of an interface in the sub interface?

What is the reason behind overriding a method/methods of an interface in the sub interface?
for example
interface I{ public void method();}
interface I2 extends I{#Override public void method();}
You may need to change the return type of your method to a sub-type of the original return type. eg:
interface I {
public Object method();
}
interface I2 extends I {
#Override
public Integer method();
}
Or you can add default implementation to the method which is introduced in Java 8. eg:
interface I {
public void method();
}
interface I2 extends I {
#Override
default public void method() {
System.out.println("do something");
}
}

How can I determine if Java generic implements a particular interface?

How can I determine if a Java generic implements a particular interface?
I have tried a few different approaches, but they all results in a "cannot find symbol ... variable T" error.
First Attempt
public abstract class AbstractClass<T> {
public void doFoo() {
if (T instanceof SomeInterface){
// do stuff
}
}
}
Second Attempt
public abstract class AbstractClass<T> {
public void doFoo() {
if (SomeInterface.class.isAssignableFrom(T)) {
// do stuff
}
}
}
You can't.
Workaround 1
Add a constructor taking the class of the object.
public abstract class AbstractClass<T> {
private Class<T> clazz;
public AbstractClass(Class<T> clazz) {
this.clazz = clazz;
}
public void doFoo() {
if (clazz instanceof SomeInterface){
// do stuff
}
}
}
Workaround 2
Add a constraint to the type T with T extends SomeInterface, thereby restricting the type T to be a subtype of SomeInterface.
public abstract class AbstractClass<T extends SomeInterface> {
public void doFoo() {
// do stuff
}
}
Put a bound on it.
public abstract class <T extends SomeInterface> { }
Then you're guaranteed that it will be at least SomeInterface when passed through as an argument to a method.
From your approach, there's no way to do it, since you don't reference an instance of T anywhere in your code. If you added an argument to it, you'd be able to at least get further.
public void doFoo(T obj) { }

Java generics static type inference

I do have an abstract class with an delegation interface defined:
public abstract class MyAbstractClass extends AsyncLoader {
public interface MyAbstractClassDelegate<M> {
//The parameter in this method should be the concrete subtype of MyAbstractClass
public M performThisCall(MyAbstractClass concreteSubclassOfAbstractClass);
}
private MyAbstractClassLoaderDelegate delegate;
...
}
The Problem is, I do not want the delegate parameter to be MyAbstractClass, instead it should be the concrete subclass. Why? Because the implementation of the delegate needs the concrete subclass for further handling and I don't want to cast it...
I know I could define an Interface in each subclass, but it'll look the same in every subclass except for the parameter type
EDIT
Here is the perfect solution solving exactly what I wanted. Great thanks!
public abstract class MyAbstractClass {
public interface MyAbstractClassDelegate<M, Subtype extends MyAbstractClass> {
public M myMethod(Subtype t);
}
}
Is this possible with java 6 and if yes - how?
My solution would be:
public final class Example<T extends Example<T>> {
public interface Interface<M, Subtype extends Interface<M, Subtype>> {
public M myMethod(Subtype t);
}
}
You have no access to the generic from the outer class inside the interface (because the interface is static) so you have to declare it again.
If you use your interface you get something like this:
private static class Impl1 implements Interface<String, Impl1> {
#Override
public String myMethod(final Impl1 t) {
return null;
}
}
I don't know if it will help but here is my complete example:
public final class Example<M, T extends Example.Delegate<M, T>> {
public interface Delegate<M, Subtype extends Delegate<M, Subtype>> {
public M myMethod(Subtype t);
}
private T delegate;
private static class Impl1 implements Delegate<String, Impl1> {
#Override
public String myMethod(final Impl1 t) {
return null;
}
}
public static void main(String[] args) {
Example<String, Impl1> example = new Example<>();
example.delegate = new Impl1();
example.delegate.myMethod(example.delegate); //works but whout?
}
}
What you could do is to give your abstract class a type parameter with the concrete subclass, similar to the way Java's Enum does it.
Something along the lines of this:
public abstract class MyAbstractClass<S extends MyAbstractClass<S>> extends AsyncLoader {
public interface MyAbstractClassDelegate<M, S> {
public M performThisCall(S concreteSubclassOfAbstractClass);
}
...

Is it possible to "overload" a generic class by using different type list?

What I want is actually something like this:
public class Foo<T> {
// ...
}
public class Foo<T, S> {
// ...
}
Note that the name of the classes are the same, but the length of type list is different. The code above doesn't work in Java, but I hope it shows my intent. Is it possible to do similar thing in Java?
Example:
public class Foo<T> {
public Integer call(T input) {
// ...
}
}
public class Foo<T, S> {
public S call(T input) {
// ...
}
}
You don't override classes, you override methods. Classes might be subclassed.
This is possible:
public class Zoo<T, S, U> extends Foo<T>
{
// ...
}
I guess this is what you are trying to do:
Class foo1.Foo:
package foo1;
public class Foo<T, S> {
public S call(T input) {
// ...
}
}
Class foo2.Foo:
package foo2;
public class Foo<T> extends foo1.Foo<T, Integer> {
public Integer call(T input) {
// ...
}
}
When you are defining a class as
public class Foo<T> {
// ...
}
Technically we are telling the compiler to replace the Generic with a Object as T is unbounded.
When we define the class as
public class Foo<T, S> {
// ...}
Compiler will not know how to resolve this.

Categories