I have the following. If I keep the #Override, I get an error that the method must implement or override a supertype method. If I remove it, I get an error that the child class must implement the inherited abstract method. Why won't the below code work, and how can I make it do what I intend?
BaseClass.java:
public abstract class BaseClass
{
...
protected abstract <T extends Inputs> T doStuff(T inputs);
public abstract static class Inputs
{
...
}
}
ChildClass.java:
public class ChildClass extends BaseClass
{
...
#Override
protected Inputs doStuff(Inputs inputs)
{
return inputs;
}
public static class Inputs extends BaseClass.Inputs
{
...
}
}
Try and:
public abstract class BaseClass<T extends BaseClass.Inputs>
and:
public class ChildClass extends BaseClass<ChildClass.Inputs>
Which means you need to change doStuff() so that it returns T (in BaseClass), without having a declared type variable:
public abstract T doStuff(T inputs);
Related
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.
I have an interface, a superclass that implements it, and a subclass that extends the superclass. Then I have test that creates an object of the type of the subclass, but stores it in a variable of the type of the interface. When I use a method that is defined in the interface, implemented in the superclass, and overridden in the subclass, it calls the method from the superclass. Why is this? I can't change the test class, but did I do something wrong with the subclass?
public interface SampleInterface<T extends Comparable<T>>{
void add(T element);
//other methods, etc
}
public class SampleClassA<T extends Comparable<T>> implements SampleInterface<T> {
public void add(){
System.out.println("super");
}
}
#Override
public class SampleClassB<T extends Comparable<T>> extends SampleClassA<T> {
public void add(){
System.out.println("sub");
}
}
Then I want to use the code in a test that looks like this:
private SampleInterface<Integer> test = new SampleClassB<Integer>();
test.add();
And it prints "super", but I want "sub". This is a simplified version of my code, also.
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);
}
...
I have the following class structure.
public abstract class X { }
public class Y extends X { }
And I want to do the following:
public abstract class Action {
public abstract <T extends X> void execute(T t);
}
public class SomeAction extends Action {
public void execute(Y y) { }
}
The compiler is giving me following error:
The Type SomeAction must implement the inherited abstract method Action.execute(T)
I do want to override execute(), but I want the parameter to be a subclass of X.
What am I doing wrong here?
Try making the class Action generic, instead of one of its methods.
public abstract class Action<T extends X>
{
public abstract void execute(T t);
}
Then you can assign the generic type parameter T to be Y in SomeAction:
public class SomeAction extends Action<Y>
{
public void execute(Y y) {}
}
It sounds like you want T extends X to be a property of the class extending Action, not the method invocation. You should write
public abstract class Action<T extends X> {
public abstract void execute(T t);
}
and then
public class SomeAction extends Action<Y> {
...
}
public <T extends X> void execute(T t);
is an abstract method as it does not have any body. it should be marked as abstract.
So in your child class you need to override this or mark both method and subclass as abstract.
You're breaking the Liskov principle: the base Action's execute method is able to execute any kind of X. But in the subclass, you limit it to executing only Y instances. That's reducing the contract, instead of extending it.
Within my code a have the following abstract superclass
public abstract class AbstractClass<Type extends A> {...}
and some child classes like
public class ChildClassA extends AbstractClass<GenericTypeA> {...}
public class ChildClassB extends AbstractClass<GenericTypeB> {...}
I'm searching for an elegant way how I can use the generic type of the child classes (GenericTypeA, GenericTypeB, ...) inside the abstract class in a generic way.
To solve this problem I currently defined the method
protected abstract Class<Type> getGenericTypeClass();
in my abstract class and implemented the method
#Override
protected Class<GenericType> getGenericTypeClass() {
return GenericType.class;
}
in every child class.
Is it possible to get the generic type of the child classes in my abstract class without implementing this helper method?
BR,
Markus
I think its possible. I saw this was being used in the DAO patterns along with generics. e.g.
Consider classes:
public class A {}
public class B extends A {}
And your generic class:
import java.lang.reflect.ParameterizedType;
public abstract class Test<T extends A> {
private Class<T> theType;
public Test() {
theType = (Class<T>) (
(ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
// this method will always return the type that extends class "A"
public Class<T> getTheType() {
return theType;
}
public void printType() {
Class<T> clazz = getTheType();
System.out.println(clazz);
}
}
You can have a class Test1 that extends Test with class B (it extends A)
public class Test1 extends Test<B> {
public static void main(String[] args) {
Test1 t = new Test1();
Class<B> clazz = t.getTheType();
System.out.println(clazz); // will print 'class B'
System.out.println(printType()); // will print 'class B'
}
}
I'm not sure I fully understand your question - <Type> is the generic type of the subclass, even when it's being expressed in the abstract class. For example, if your abstract superclass defines a method:
public void augment(Type entity) {
...
}
and you instantiate a ChildClassA, you'll only be able to call augment with an instance of GenericTypeA.
Now if you want a class literal, then you'll need to provide the method as you indicated. But if you just want the generic parameter, you don't need to do anything special.