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.
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.
Say I have a class
abstract class A {
ArrayList<?> l;
public void setList(ArrayList<?> l) //set the list
}
Is it possible to do something like
class B extends A {
public void setList(ArrayList<? extends Foo> l) //Set the list }
I basically would like to specify an abstract class with a parameterised field, where a class inheriting from the first class can specify the type of the field more specifically so that it must extend some other type.
Can a subclass in Java override a set method and make the argument type more specific?
No. When overriding a method the signatures (name and argument types) have to be the same after type erasure. See JLS 8.4.2 for more information.
I basically would like to specify an abstract class with a parameterised field, where a class inheriting from the first class can specify the type of the field more specifically so that it must extend some other type.
abstract class A<T> {
public abstract void setList(ArrayList<? extends T> l);
}
class B extends A<Integer> {
#Override
public void setList(ArrayList<? extends Integer> l) {
//...
};
}
Here the compiler will perform type erasure and the signatures will be identical.
You would need to make A generic:
abstract class A<T> {
abstract void setList(List<? extends T> list);
}
And then make B something like:
class B extends A<Foo> {
#Override void setList(List<? extends Foo> list) { ...}
}
It will work if you generify the base class:
abstract class A<T> {
ArrayList<T> l;
public void setList(ArrayList<T> l) {//set the list
}
}
class B<T extends Foo> extends A<T> {
#Override
public void setList(ArrayList<T> l) {//Set the list
}
}
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 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);
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);
}
...