How to Make a Java Class That Implements One Interface with Two Generic Types

How to make a Java class that implements one interface with two generic types?

Consider encapsulation:

public class TwoTypesConsumer {
private TomatoConsumer tomatoConsumer = new TomatoConsumer();
private AppleConsumer appleConsumer = new AppleConsumer();

public void consume(Tomato t) {
tomatoConsumer.consume(t);
}

public void consume(Apple a) {
appleConsumer.consume(a);
}

public static class TomatoConsumer implements Consumer<Tomato> {
public void consume(Tomato t) { ..... }
}

public static class AppleConsumer implements Consumer<Apple> {
public void consume(Apple a) { ..... }
}
}

If creating these static inner classes bothers you, you can use anonymous classes:

public class TwoTypesConsumer {
private Consumer<Tomato> tomatoConsumer = new Consumer<Tomato>() {
public void consume(Tomato t) {
}
};

private Consumer<Apple> appleConsumer = new Consumer<Apple>() {
public void consume(Apple a) {
}
};

public void consume(Tomato t) {
tomatoConsumer.consume(t);
}

public void consume(Apple a) {
appleConsumer.consume(a);
}
}

How to implement the same interface multiple times, but with different generics?

You need to use inner or anonymous classes. For instance:

class Foo {
public EventListener<X> asXListener() {
return new EventListener<X>() {
// code here can refer to Foo
};
}

public EventListener<Y> asYListener() {
return new EventListener<Y>() {
// code here can refer to Foo
};
}
}

Implementing multiple generic interfaces

There is only one handle(Object) method in reality. You are effectively write the same as

public class CompositeListener implements EventListener {
public void handle(Object event) {
if (event instanceof PriceUpdate) {
///
} else if (event instanceof OrderEvent) {
///
}
}
}

Without this checking logic, you can't effectively call your event listener in any case.

Generic which is required to implement two interfaces

you can use Multiple Bounds like <T extends CanFly & CanRun>

Note: in future if you want to add a class along with CanFly & CanRun then make sure to put the class at the beginning like <T extends className & CanFly & CanRun> otherwise it will raise an exception

Java Generics With a Class & an Interface - Together

Actually, you can do what you want. If you want to provide multiple interfaces or a class plus interfaces, you have to have your wildcard look something like this:

<T extends ClassA & InterfaceB>

See the Generics Tutorial at sun.com, specifically the Bounded Type Parameters section, at the bottom of the page. You can actually list more than one interface if you wish, using & InterfaceName for each one that you need.

This can get arbitrarily complicated. To demonstrate, see the JavaDoc declaration of Collections#max, which (wrapped onto two lines) is:

public static <T extends Object & Comparable<? super T>> T
max(Collection<? extends T> coll)

why so complicated? As said in the Java Generics FAQ: To preserve binary compatibility.

It looks like this doesn't work for variable declaration, but it does work when putting a generic boundary on a class. Thus, to do what you want, you may have to jump through a few hoops. But you can do it. You can do something like this, putting a generic boundary on your class and then:

class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
Class<T> variable;
}

to get variable that has the restriction that you want. For more information and examples, check out page 3 of Generics in Java 5.0. Note, in <T extends B & C>, the class name must come first, and interfaces follow. And of course you can only list a single class.

How can I define a generic class that implements two interfaces?

You can give multiple bounds to type parameter:

public interface AbstractSortedSimpleList<T extends Comparable<T> & Alike>

Then, your SortedSimpleList would be like:

class SortedSimpleList<T extends Comparable<T> & Alike> implements AbstractSortedSimpleList<T> {}

See JLS §4.4:

Every type variable declared as a type parameter has a bound. If no bound is declared for a type variable, Object is assumed. If a bound is declared, it consists of either:

  • a single type variable T, or

  • a class or interface type T possibly followed by interface types I1 & ... & In.

Note:

You can't have such multiple bounds for wildcards though. It's only for type parameters.

References:

  • Java Generics FAQs - Type Parameter bounds

How to implement a generic interface that extends another generic interface in Java?

I think it's worth inspecting which identifier means what in this case. Let's look at the base interface first GenericItemProviderInterface<Req, ExtReq, ExtRes, Res>.

Here all 4 type parameters Req, ExtReq, ExtRes and Res are type parameters. That's important to remember, because they are not themselves types!

Then let's look at the definition of the derived interface: ItemsProviderInterface<ExtReq, ExtRes> only has 2 type parameters: ExtReq and ExtRes. Note that despite the identical names, those don't inherently have anything to do with the ones on the base interface. That connection comes now:

interface ItemsProviderInterface<ExtReq, ExtRes> 
extends GenericItemProviderInterface<ItemRequest, ExtReq, ExtRes, ItemResponse>

This means that an ItemsProviderInterface is-a GenericProviderInterface with the 4 type parameters set like this:

  • Req of GenericItemProviderInterface is set to the actual type (class or interface) ItemRequest.
  • ExtReq of GenericItemProviderInterface is set to the type parameter ExtReq of ItemsProviderItnerface
  • ExtRes of GenericItemProviderInterface is set ot the type parameter ExtRes of ItemsProviderInterface
  • Res of GenericItemProviderInterface is set to the actual type ItemResponse.

So 2 of the 4 type parameters of the base-class are "fixed" to a specific type and the remaining two are left variable.

If you now implement ItemProviderInterface you could either also have 2 type parameters and route them to ExtReq/ExtRes or fix them to specific classes (or do 1-and-1, but that's probably not useful for this specific example.

So either

class MyItemProvider<ExtReq, ExtRes>
implements ItemProviderInterface<ExtReq, ExtRes> {...}

or

class MySpecificItemProvider
implements ItemProviderInterface<MySpecificExtReq, MySpecificExtRes> {...}

Is it possible to have two different generic types (such as T) in a Java interface?

Yes you can have multiple generic types.

public interface Processor<T, S> {
T update( S id );
T find( S id );
List<T> findAll( List<S> ids );
}

Implementing Generic Interface in Java

You can't do that in Java. You can only implement one concrete realization of the same generic interface. I would do this instead:

public class AddressHandler implements Handles<Event>{
public void handle(Event e){
if(e instanceof AddressDiscarded){
handleDiscarded(e);
} else if(e instanceof AddressChanged){
handleChanged(e);
}
}
public void handleDiscarded(AddressDiscarded e){}
public void handleChanged(AddressChanged e){}
}


Related Topics



Leave a reply



Submit