I have interface:
public interface CartService extends RemoteService{
<T extends ActionResponse> T execute(Action<T> action);
}
I wish override 'execute' method in implementation:
public class XX implements CartService {
#Override
public <GetCartResponse> GetCartResponse execute(GetCart action) {
// TODO Auto-generated method stub
return null;
}
}
But receive compiler error:
The method execute(GetCart) of type XX must override or implement a supertype method
GetCart & GetCartResponse:
public class GetCart implements Action<GetCartResponse>{
}
public class GetCartResponse implements ActionResponse {
private final ArrayList<CartItemRow> items;
public GetCartResponse(ArrayList<CartItemRow> items) {
this.items = items;
}
public ArrayList<CartItemRow> getItems() {
return items;
}
}
How can I override this method ?
The problem is the definition of the interface vs what the erausre should look like for your impl. In your example you have:
<T extends ActionResponse> T execute(Action<T> action);
public <GetCartResponse> GetCartResponse execute(GetCart action);
but according to the interface definition the implementation method should read:
public GetCartResponse execute(Action<GetCartResponse> action);
So I think you either need to change the signature of your interface or add another type parameter such as:
public interface CartService extends RemoteService{
<T extends ActionResponse, U extends Action> T execute(U action);
}
or possibly something along the lines of:
public interface CartService extends RemoteService{
<T extends ActionItem> ActionResponse<T> execute(Action<T> action);
}
Your interface specifies that implementing classes must define that method for all T extends ActionResponse. You want to define them for specific actions, and responses - I think your interface needs to be
public interface CartService<T extends ActionResponse, A extends Action<T>>
extends RemoteService {
public T execute(A action)
}
and then implementation would be
public class XX implements CartService<GetCartResponse,GetCart> {
//...
}
As written, you may not need to explicitly parametrize with an extension of Action type - as long as you can deal with any kind of Action that is parametrized by GetCartResponse and don't rely on specifics of the GetCart action. In which case, your interface should look something like:
public interface CartService<T extends ActionResponse> extends RemoteService {
public T execute(Action<T> action);
}
and implementation
public class XX implements CartService<GetCartResponse> {
public GetCartResponse execute(Action<GetCartResponse> action) {
//...
}
}
Use
public <GetCartResponse extends ActionResponse>
GetCartResponse execute(GetCart action) {
//do stuff
}
as the signature for the execute method in CartService, it should work.
I ahve tested that the follwing compiles; just substituted ActionResponse with Integer, and Action with List, for convenience.
CartService:
public interface CartService {
<T extends Integer> T execute(List<T> action);
}
XX:
public class XX implements CartService {
public <T extends Integer> T execute(List<T> action) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
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) {
}
}
I want to have an abstract Java class like this:
abstract class AbstractFoo<F extends AbstractFoo<F, L>, L extends FooListener<F, L>> {
private final Class<L> listenerClass;
protected AbstractFoo(Class<L> listenerClass) {
this.listenerClass = listenerClass;
}
interface FooListener<F extends AbstractFoo<F, L>, L extends FooListener<F, L>> {
void callback(F foo);
}
// Bar might implement FooListener, but I don't control it,
// so I have no guarantee
public void externalMethod(Bar bar) {
if (listenerClass.isInstance(bar)) {
L listener = listenerClass.cast(bar);
listener.callback(this); // does not compile
}
}
}
listener.callback(this); doesn't compile because there's no guarantee that this is the same type as F. Is it possible to somehow guarantee that F is a supertype of this?
What you are trying to do is emulate the SELF type in Java using generics. See this link or a different site for some means to do so. However, there is no way to enforce that F (or the SELF type) is actually the same type, for example (see type parameter of ConcreteFoo2):
static class Bar implements FooListener<ConcreteFoo, Bar> {
#Override
public void callback(final ConcreteFoo foo) {
// TODO Auto-generated method stub
}
}
static class ConcreteFoo2 extends AbstractFoo<ConcreteFoo, Bar> {
protected ConcreteFoo2(final Class<Bar> listenerClass) {
super(listenerClass);
}
}
static class ConcreteFoo extends AbstractFoo<ConcreteFoo, Bar> {
protected ConcreteFoo(final Class<Bar> listenerClass) {
super(listenerClass);
}
}
Instead of further going this way, I would first think about the design choices made that led you here:
Do the listeners really need to know the concrete class?
Does the AbstractFoo really need to know the concrete implementation of the listener class?
Maybe fewer type parameters are actually the solution, relying on the interfaces alone.
EDIT: One possible solution, if you don't want to cast (F) this would be to provide an abstract method protected abstract F getSelf(); that the concrete implementations implement by returning this.
See this simplified code for example:
static final class Bar implements FooListener<ConcreteFoo> {
#Override
public void callback(final ConcreteFoo foo) {
// TODO Auto-generated method stub
}
}
static final class ConcreteFoo extends AbstractFoo<ConcreteFoo> {
protected ConcreteFoo(final Class<? extends FooListener<ConcreteFoo>> listenerClass) {
super(listenerClass);
}
#Override
protected ConcreteFoo getSelf() {
return this;
}
}
static abstract interface FooListener<FOO extends AbstractFoo<FOO>> {
void callback(FOO abstractFoo);
}
static abstract class AbstractFoo<SELF extends AbstractFoo<SELF>> {
private final Class<? extends FooListener<SELF>> listenerClass;
protected AbstractFoo(final Class<? extends FooListener<SELF>> listenerClass) {
this.listenerClass = listenerClass;
}
protected abstract SELF getSelf();
// Bar might implement FooListener, but I don't control it,
// so I have no guarantee
public void externalMethod(final Bar bar) {
if (listenerClass.isInstance(bar)) {
final FooListener<SELF> listener = listenerClass.cast(bar);
listener.callback(getSelf()); // compiles
}
}
}
Using a library with an abstract class A and interfaces I and J, I get the following warning message when I extend / implement the class / interfaces:
Missing type arguments for generic class J<T>.
As a MWE, the classes are as follows (T and S are generic type parameters):
public abstract class A {}
public interface I<T extends A> {
public <S extends T> void doStuff(J<? super S> param);
}
public interface J<T extends A> {
public void doOtherStuff();
}
Here are my classes:
public class AExtended extends A {}
public class IImplemented implements I<AExtended> {
#Override
public void doStuff(J param) {}
}
Explicitly using the class AExtended as below does not properly implement doStuff() from I:
public class IImplemented implements I<AExtended> {
#Override
public void doStuff(J<AExtended> param) {}
}
You're not overriding doStuff in IImplemented because the method is not generic and the type bounds are not present. This version of doStuff should work for you:
public <S extends AExtended> void doStuff(J<? super S> param) {}
Notice that since the type of I is AExtended it is used appropriately here, and the lower bound in the wildcard type for J is also included.
try with:
public class IImplemented implements I<AExtended> {
#Override
public <S extends AExtended> void doStuff(J<? super S> param) {
// ...
}
}
Let's say I have a generic builder type:
public abstract class Builder<T> {
public abstract T build();
}
Then a Foo class and a builder for it, which extends Builder:
public class Foo {
// stuff
}
public class FooBuilder extends Builder<Foo> {
public Foo build() {
return new Foo();
}
}
I also have an abstract, generic Handler type:
public abstract class Handler<T> {
public abstract <U extends Builder<T>> void handle(U builder);
}
and finally a FooHandler:
public class FooHandler extends Handler<Foo> {
#Override
public void handle(FooBuilder builder) {
// do something
}
}
The issue is that FooHandler's handle() is not recognized as overriding Handler's handle(): Method does not override method from its superclass. Is it possible to do this?
Move the type parameter to the class level
abstract class Handler<T, U extends Builder<T>> {
public abstract void handle(U builder);
}
class FooHandler extends Handler<Foo, FooBuilder> {
#Override
public void handle(FooBuilder builder) {
// do something
}
}
Problem:
I have two interfaces (here GenCarry and Gen):
public interface GenCarry<T extends Gen> {
GenCarry<T> setGen(T gen);
}
public interface Gen<T extends GenCarry> {
void applyOn(T carry);
}
It works when I ignore the 'rawtypes' Warning, but trying to complete them I don't get too far:
GenCarry<T extends Gen<GenCarry<T>>>
Gen<C extends GenCarry<Gen<C>>> -> error: not a valid substitute for the bounded parameter.
Question:
How would an interface like that look if complete - or is that even possible?
Is there a better approach to "generalize" an interface like that?
You can define two type parameters:
public interface GenCarry<K extends GenCarry<K, T>, T extends Gen<T, K>> {
GenCarry<K, T> setGen(T gen);
}
public interface Gen<K extends Gen<K, T>, T extends GenCarry<T, K>> {
void applyOn(T carry);
}
class StringGenCarry implements GenCarry<StringGenCarry, StringGen> {
#Override
public StringGenCarry setGen(StringGen client) {
...
}
}
class StringGen implements Gen<StringGen, StringGenCarry> {
#Override
public void applyOn(StringGenCarry network) {
...
}
}