The below #Override annotation indicates that I am not overriding the method defined in the interface. How do I use generics with my concrete class so that it overrides the interface method?
public interface AInterface<T extends MyType> {
void do(T thing)
}
public abstract class BaseMyClass implments AInterface {
// other stuff
}
// AType extends MyType
public class MyClass extends BaseMyClass <AType> {
#Overide
public void doThing(AType atype) {
}
}
BaseMyClass is implementing the rawtype of AInterface, you either need to extend the generic to the abstract class itself or define it:
public abstract class BaseMyClass implments AInterface<AType>
public abstract class BaseMyClass<E extends MyType> implments AInterface<E>
BaseClass<AType> (assuming you meant BaseMyClass) isn't actually giving you a AInterface<AType>
Related
I want to combine the use of bounded type parameters with DI spring. That is, I would like to declare an interface:
public abstract class BaseClass {
}
public class ChildClass extends BaseClass {
}
public interface SomeInterface {
<T extends BaseClass> void update(T impl);
}
and make its implementation:
#Service
public class Impl1 extends SomeInterface {
#Override
void update(ChildClass impl) {
}
}
That is, I want to declare in the interface a general type condition for implementations and use a specific type of successor in the implementation.
Is it possible?
You can:
public interface SomeInterface<T extends BaseClass> {
void update(T impl);
}
and then:
#Service
public class Impl1 extends SomeInterface<ChildClass> {
#Override
void update(ChildClass impl) {
}
}
let me state my situation first:
I've, in a 3rd party SDK, a base class with generic type:
public abstract class BaseClass<T extends BaseDataType> {
public abstract class BaseDataType {xxx}
public abstract int getCount();
public abstract someMethod(T t);
}
in my business environment, it extends BaseClass as follows:
public abstract class MyGeneralBaseClas<`how to write this???`> extends BaseClass {
#Override public int getCount() {return some_list.size()};
#Override public abstract someMethod(`how to write this???`);
}
in the real business, I write my class:
public class MyClass extends MyGeneralBaseClass<MyDataType> {
#Override public someMethod(MyDataType type) {xxx}
}
public class MyDataType extends BaseClass.BaseDataType {
xxx
}
but the code failed to compile. sorry I'm travelling and I don't have my IDE and development tools, so I cannot paste the error. but I think if you write this down in an IDE such IntelliJ Idea, it would give the error I'm encountering.
so how to write this case: inheritance of generic type, and inheritance of the class using the generic type.
what i want is, in MyClass uses the concrete class MyDataType instead of the abstract BaseDataType.
It seems MyGeneralBaseClas should have a generic type parameter with the same type bound as BaseClass:
public abstract class MyGeneralBaseClas<T extends BaseDataType> extends BaseClass<T> {
#Override public int getCount() {return some_list.size()};
#Override public abstract someMethod(T t);
}
You can do it in two ways:
By using BaseDataType class as is, e.g.:
abstract class MyGeneralBaseClas<T extends BaseDataType> extends BaseClass<T> {
#Override public void someMethod(T t){}
}
By extending BaseDataType class, e.g.:
class DerivedDataType extends BaseDataType{
//Some code
}
abstract class MyAnotherBAseClass<DerivedDataType> extends BaseClass{
#Override
public void someMethod(com.gamesys.application.BaseDataType t) {}
}
This is a bit convoluted if you can follow along. I have this:
public interface Interface1<T> {
void method1(T t);
}
public interface Interface2 { }
public interface Interface3 extends Interface1<Interface2> { }
abstract public class BaseClass<P extends Interface1> {
P p;
void method2() {
p.method1(this);
}
}
public class Concrete extends BaseClass<Interface3> implements Interface2 {
}
Interface2 and Interface3 will change with different implementations of BaseClass. The problem is in BaseClass method2 because this is not of type Interface2 which is what it expects in this specific case. It compiles and runs but it warns about an unchecked call.
I tried implementing the interface in the base class instead of the concrete class like this
abstract public class BaseClass<P extends Interface1, V> implements V
public class Concrete extends BaseClass<Interface3, Interface2>
but Java doesn't like it. Any ideas how to do this?
To solve
interface Interface2 { }
interface Interface1<T> {
void method1(T t);
}
interface Interface3 extends Interface1<Interface2> { }
abstract class BaseClass<P extends Interface1<Interface2>>
implements Interface2{
P p;
void method2() {
p.method1(this);
}
}
class Concrete extends BaseClass<Interface3> implements Interface2 { }
It compile without any warning, the only change I made is:
abstract class BaseClass<P extends Interface1<Interface2>> implements Interface2
If you don't want to BaseClass implements directly Interface2 you can create a "marker":
interface InterfaceFOO {} // <------------ Marker without methods
interface Interface2 extends InterfaceFOO{ } // <----- harmless extend
interface Interface1<T> {
void method1(T t);
}
interface Interface3 extends Interface1<InterfaceFOO> { }
abstract class BaseClass<P extends Interface1<InterfaceFOO>>
implements InterfaceFOO{
P p;
void method2() {
p.method1(this);
}
}
class Concrete extends BaseClass<Interface3> implements Interface2 { }
I am unable to compile a method which needs to override a method from an abstract class supertype which uses generics for one of the parameters. The compiler complains that the extending class' setRef() method does not override a method from the supertype.
Parent Abstract Class:
public abstract class AbsClass<Q extends Interf> {
public abstract Ref<? extends AbsClass<Q>> getRef();
public abstract <M extends AbsClass<Q>> void setRef(Ref<M> newRef);
}
Ref is:
public interface Ref<M extends AbsClass<? extends Interf>> { }
and Interf is:
public interface Interf { }
Extending Child Class (setRef() doesn't compile):
public class ChildClass extends AbsClass<InterfImpl> {
#Override
public Ref<ChildClass> getRef() {
return null;
}
#Override
public <M extends ChildClass> void setRef(Ref<M> newRef) {
return null;
}
}
I have also tried using wildcards, and received same error. With wildcards, the abstract class' setRef() is:
public abstract void setRef(Ref<? extends AbsClass<Q>> newRef);
and the extending class' setRef() is:
public void setRef(Ref<ChildClass> newRef)
or even:
public void setRef(Ref<? extends ChildClass> newRef)
The only way I can get it to compile is if the extending class' setRef() uses the abstract class' type:
public <M extends AbsClass<Interf>> void setRef(Ref<M> newRef)
But I would like to limit the typing of the newRef parameter to be Ref<ChildClass> or subtypes, so this isn't perfect. How can I get my extending class to only allow ChildClass or its subtypes for the setRef() method's newRef parameter? Part of my confusion is that the ChildClass' getRef() return value handles the generic typing just fine, and the same "signature" on setRef()'s parameters fails to compile. Help? Thanks!
The problem with setRef is that you could access an instance of ChildClass through a variable of type AbsClass<? extends Interf> and thus the parameter type for setRef would look like <M extends AbsClass<? extends Interf>> which again could be any M but which also doesn't match <M extends AbsClass<Q>> since Q has been defined to be InterfImpl in your case.
You could change ChildClass to this:
public <M extends AbsClass<InterfImpl>> void setRef(Ref<M> newRef)
but this would still allow any M and you can't just use Ref<ChildClass> because what I said above, i.e. the compiler wouldn't know about Ref<ChildClass> if you used a variable of type AbsClass<InterfImpl> or even AbsClass<? extends InterfImpl>.
One way to allow only for ChildClass parameters would be to use ChildClass in the generic type as well, e.g. like this:
public abstract class AbsClass<Q extends Interf, M extends AbsClass<Q, M>> {
public abstract Ref<M> getRef();
public abstract void setRef(Ref<M> newRef);
}
public class ChildClass extends AbsClass<InterfImpl, ChildClass> {
public Ref<ChildClass> getRef() { return null; }
public void setRef(Ref<ChildClass> newRef) { }
}
You are getting an error because in AbsClass.setRef(), your parameter is of type Ref<? extends AbsClass<Q>>
But in your ChildClass.setRef() the parameter is of type Ref<? extends ChildClass>.
For overriding, a subclass should have the same typed parameters in the method as it's parent (before type erasure when using Generics).
I am using Jersey and have exposed a resource Resource which implements an Interface. One of the methods from Interface has a parameter a of type A which is an abstract class.
Here is some code for explanation:
//Interface.java
public interface Interface {
public void setA(A a);
}
//Resource.java
#Path("/hello")
public class Resource implements Interface {
#POST
public void setA(A a){ //Here I want to specify AImpl instead of A
//Code that uses AImpl
}
}
//A.java
public abstract class A{
//Some abstract stuff
}
//AImpl.java
public class AImpl extends A{
//Some concrete stuff
}
This leads to an error:
JsonMappingException: Can not construct instance of A, problem: abstract types can only be instantiated with additional type information
How can this be avoided/ overcome?
One solution would be to make Jersey/Jackson aware that it can use the concrete implementation of A (which is AImpl) in method setA() of Resource. Is there any annotation that I can use to do that?
Have you considered simply making Interface generic? Something like
public abstract class SuperType {}
public class SubType extends SuperType {}
public interface Resource<T extends SuperType> {
Response doSomething(T type);
}
#Path("resource")
public class SubTypeResource implements Resource<SubType> {
#POST
#Override
public Response doSomething(SubType type) {
...
}
}