Java Generics and Bounded parameters in subclasses - java

I'm trying to understand how to use generics in the form of a bounded type parameter in an interface. In this case, to avoid casting when using the bounded param in concrete implementations but I'm running into an issue. I will use the following example to illustrate my problem:
There's an interface and two concrete implementations
public abstract class Publication {
}
public class Newspaper extends Publication {
}
public class Newspaper extends Publication {
}
Then we have an interface representing a publishing house with two concrete implementations, one publishes magazine and the other newspapers
public interface Publisher {
public <T extends Publication >void publish(T publication);
}
Here are the two implementations
//DOES NOT COMPILE
public class MagazinePublisher implements Publisher{
#Override
public void publish(Magazine publication) {
//do something with the magazine, its already the type we need without casting
}
}
//COMPILES but a cast is required to get the type I want
public class NewsPaperPublisher implements Publisher{
#Override
public void publish(Publication publication) {
// Now I need to cast
Newspaper newspaper = (Newspaper)publication;
//Do some stuff here
}
}
The example maybe a bit contrived... I understand why the MagazinePublisher class doesn't compile: I'm trying to implement the method with a more specific class than defined by the contract of the publish method in the interface. So how do I user generics to avoid the cast in the NewsPaperPublisher class's publish() method?

You want to make the interface generic.
public interface Publisher <T extends Publication> {
void publish(T publication);
}
Then, instead of NewspaperPublisher and MagazinePublisher, you can just write Publisher<Newspaper> and Publisher<Magazine>.
Or if you want to provide different implementations depending on the type, you can write things like
public class NewspaperPublisher implements Publisher<Newspaper> {
#Override
public void publish(Newspaper publication) {
// do some stuff
}
}

Related

Cumbersome generics declaration in a huge Java classes hierarchy

I have basically two types of each entity in my project which are distinguisched only by specifying the parent catalog type in the class generics declaration. Catalogs iteself are declared with generics as they can have links to a specific old catalog of the same type.
abstract class AbstractCatalog<T extends AbstractCatalog<T>> {
public abstract T getOld();
}
class Catalog1 extends AbstractCatalog<Catalog1> {
#Override
public Catalog1 getOld() { ... }
}
class Catalog2 extends AbstractCatalog<Catalog2> {
#Override
public Catalog2 getOld() { ... }
}
So far so good but the problem is that it becomes really cumbersome if I add some entities that must contain a link to a catalog of a certain type.
For instance,
abstract class AbstractCatalogHistory<C extends AbstractCatalog<C>, E extends AbstractHistoryEntry<C, E>> {
public abstract Set<E> getEntries();
}
abstract class AbstractHistoryEntry<C extends AbstractCatalog<C>, E AbstractHistoryEntry<C, E>> {
public abstract E getPrior();
}
class Cat1HistoryEntry extends AbstractHistoryEntry<Catalog1, Cat1HistoryEntry> {
#Override
public Cat1HistoryEntry getPrior() { ... }
}
class Cat2HistoryEntry extends AbstractHistoryEntry<Catalog2, Cat2HistoryEntry> {
#Override
public Cat2HistoryEntry getPrior() { ... }
}
class Catalog1History extends AbstractCatalogHistory<Catalog1, Cat1HistoryEntry> {
#Override
public Set<Cat1HistoryEntry> getEntries() { ... }
}
class Catalog2History extends AbstractCatalogHistory<Catalog2, Cat2HistoryEntry> {
#Override
public Set<Cat2HistoryEntry> getEntries() { ... }
}
so it gets much more difficult to get idea of what's going on while looking at such a hierarchy. This example is by no means complete and I have dozens of types that should be nested within those I provided above.
What I'm trying to do by doing this is to take advantage of type safe code which can be verified at compile time. But at the same time such a code becomes completely messy as I have to specify longer generics chains while adding new types to the hierarchy.
Is there a way to handle such generics explosion?
Your example doesn't make it entirely clear why you need to have separate classes for Catalog1 and Catalog2, but let's assume this is set.
However, even so I see no reason why everything else referencing these catalogs would require this kind of duplication. If you just want to make sure it's associated with the right catalog type, then this is the only generic parameter you should really need:
class CatalogHistory<C extends AbstractCatalog<C>> {
public Set<HistoryEntry<C>> getEntries();
}
class HistoryEntry<C extends AbstractCatalog<C>> {
public HistoryEntry<C> getPrior();
}
But what if you are actually doing different things in e.g. Cat1HistoryEntry and Cat2HistoryEntry so you need the separate classes? In that case you can obviously not get around having the abstract base class and two concrete implementations, but I see no need to introduce generic types and then nail them down to the concrete types the way you do:
abstract class AbstractHistoryEntry<C extends AbstractCatalog<C>> {
public abstract AbstractHistoryEntry<C> getPrior();
}
class Cat1HistoryEntry extends AbstractHistoryEntry<Catalog1> {
#Override
public Cat1HistoryEntry getPrior() { ... }
}
class Cat2HistoryEntry extends AbstractHistoryEntry<Catalog2> {
#Override
public Cat2HistoryEntry getPrior() { ... }
}
There are a few things going on here. First, consider AbstractHistoryEntry. If you have one of those, you are working on a generic level and should not care that getPrior returns this or that concrete subtype - all you need to know is that it returns another AbstractHistoryEntry object referencing the same catalog.
If you have a concrete Cat1HistoryEntry reference however, you can still get the full type safety of getting another Cat1HistoryEntry out of getPrior thanks to the covariance of return types in Java.
Now it gets slightly more complicated - Let's try to pull the same trick with AbstractCatalogHistory:
abstract class AbstractCatalogHistory<C extends AbstractCatalog<C>> {
public abstract Set<? extends AbstractHistoryEntry<C>> getEntries();
}
class Catalog1History extends AbstractCatalogHistory<Catalog1> {
#Override
public Set<Cat1HistoryEntry> getEntries() { ... }
}
class Catalog2History extends AbstractCatalogHistory<Catalog2> {
#Override
public Set<Cat2HistoryEntry> getEntries() { ... }
}
As you can see, both concrete subclasses still return a set of the concrete types Cat1HistoryEntry and Cat2HistoryEntry. The abstract base type now needs to express a common supertype for those sets so that you can work with the result in a generic way. This is done by introducing covariance.
Setters
Setters complicate the matter a bit. Basically, if you have a generic container / collection like a List<T> or an AbstractCatalogHistory<C>, and you want to allow both adding and retrieving items, you can no longer have variance in the item type if you want type safety.
For example, if you had a setter in AbstractCatalogHistory<C> which allows you to add any AbstractHistoryEntry<C> items to the history, then you have a problem, because if your AbstractCatalogHistory<C> is actually a Catalog1History then you only want Cat1HistoryEntry items in there!
This is the same problem as with generic lists: A List<Cat> is not a List<Mammal> because you can add an elephant to a List<Mammal>, but you shouldn't be able to add an elephant to a List<Cat>.
If you insist that a history for Catalog1 must consist only of Cat1HistoryEntry items, then a solution would be to only add a setter to Catalog1History, and none to AbstractCatalogHistory<C>. That way the generic classes would only be used for reading the history, not writing it.
However, going back to the beginning of my answer: If you don't actually don't need the dual concrete classes, the solution remains very simple. Unfortunately you still didn't explain why or if you need those. If all you really want is the Catalog1 / Catalog2 distinction, and you don't actually need a different implementation for e.g. Cat1HistoryEntry and Cat2HistoryEntry, then the following should suffice:
class CatalogHistory<C extends AbstractCatalog<C>> {
public Set<HistoryEntry<C>> getEntries();
public void addEntry(HistoryEntry<C> entry);
}
class HistoryEntry<C extends AbstractCatalog<C>> {
public HistoryEntry<C> getPrior();
public void setPrior(HistoryEntry<C> prior);
}

Best practices in achieving a great cohesion from multiple interfaces

First, sorry for imperfection in my wording, just let me know if there are unclear points.
While I am building the class structure of a java application, I wonder if there are the known best practices that I've not found yet in my case.
For example, There are A, B, C and more classes specifying device types, and each device has a tokenizer, parser, and compiler.
First, I have four interfaces like these.
interface Device {
public void x();
public int y();
public String z();
...
}
interface Tokenizer {...}
interface Parser {...}
interface Compiler {...}
And, the actual concrete classes are,
public class ADevice implements Device {...}
public class BDevice implements Device {...}
public class CDevice implements Device {...}
class ATokenizer implements Tokeninzer {...}
class BTokenizer implements Tokeninzer {...}
class CTokenizer implements Tokeninzer {...}
class AParser implements Parser {...}
...
class ACompiler implements Compiler {...}
...
Additionally and importantly, the "Device" classes and its interface are public so that will be contained in a stub lib. Anything else will only be included in the actual library and not visible to users who generate scripts by referring to the API.
Here is my question, (Long introduction :[ )
How to achieve the cohesion between each type and its corresponding interfaces.
In more detail, is there a way to determine whether they are paired right, between each type of device interface and its corresponding tokenizer, parser, or compiler interface in a compile time?
For example, there is a manager class that uses "Device" objects and "Tokenizer", "Parser", and "Compiler" objects. As you can see, "ADevice" objects can only be a pair with "ATokenizer", "AParser", or "ACompiler". However, if we define their type of the device objects from the interface, then there is no way we can tell if those objects are corresponding to the right "Tokenizer", "Parser", or "Compiler" object, except that "instanceOf" operator in a run time.
For instance, "ADevice" can be matched with "BTokenizer", "CParser", and so forth, and that will not generate the compile error.
I hope that I would like to hear a good answer or redirect to references.
One solution would be to paramaterize your interfaces:
interface Tokenizer<D extends Device> { ... }
interface Parser<D extends Device> { ... }
interface Compiler<D extends Device> { ... }
Then your implementations would be:
class ATokenizer implements Tokeniser<ADevice> { ... }
class BTokenizer implements Tokenizer<BDevice> { ... }
class CTokenizer implements Tokenizer<CDevice> { ... }
class AParser implements Parser<ADevice> { ... }
.
.
.
class ACompiler implements Compiler<ADevice> { ... }
You could then have a method in your Manager class that restrict them to the same type:
public <D extends Device> void doStuff(Tokeizer<D> tokenizer, Parser<D> parser, Compiler<D> compiler) { ... }
The compiler would then only allow it to be used as you descibe:
doStuff(new ATokeizer(), new AParser(), new ACompiler()); // works
doStuff(new ATokeizer(), new AParser(), new BCompiler()); // compiler error
Have you thought about generic interfaces?
With interface like below:
public interface Parser<E extends Device> {
void parse(E device);
void parse(String someString);
}
You could create class like this:
public class AParser implements Parser<ADevice> {
#Override
public void parse(ADevice device) {
//parse...
}
#Override
void parse(String someString) {
//parse...
}
}

Inheriting from a generic interface multiple times while respecting variance

I ran into a problem when trying to specialize a class that implements a generic interface where I wanted to inherit from the same interface as the super class, but with a more specific type argument. The following snippet shows a synthetic but complete example that cannot be compiled. The comment contains the error message from the Java compiler.
interface Producer<T> {
T get();
}
class NumberProducer implements Producer<Number> {
#Override
public Number get() { return null; }
}
// Producer cannot be inherited with different arguments: <java.lang.Integer> and <java.lang.Number>
class IntegerProducer extends NumberProducer implements Producer<Integer> {
#Override
public Integer get() { return null; }
}
In the PECS sense, Producer<T> is a producer, so Producer<Integer> would be a subtype of Producer<Number>, but there's no way to declare that in the definition of Producer<T>. Java does not allow IntegerProducer to inherit from NumberProducer and Producer<Integer> at the same time as IntegerProducer would then inherit from Producer<Integer> and Producer<Number> at the same time.
Is there a standard approach to this limitation, e.g. a pattern that solves the same problem without requiring this kind of inheritance?
Just add a parameter to the super class:
interface Producer<T> {
T get();
}
class NumberProducer<T extends Number> implements Producer<T> {
#Override
public T get() { return null; }
}
class IntegerProducer extends NumberProducer<Integer> { // Implicit: implements Producer<Integer>
#Override
public Integer get() { return null; }
}
Say we had a simple Method gimme.
public static <T> T gimme(Producer<T> p) { return p.get(); }
Within the context of gimme nothing is known about T. It could be Number, Integer or any other reference type. So, due to erasure, the compiler emits an interface call to Producer.get()Object rather than the specific call to, say, IntegerProducer.get()Integer. All types that implement Producer<T> with T != Object also implicitly implement Producer.get()Object. This implicit implementation forwards to the specific implementation. That might be NumberProducer.get()Number or IntegerProducer.get()Integer, but not both. That's why you can't implement the same interface twice.
Other languages allow this via definition site variance, where Producer<Integer> is a subtype of Producer<Number>, but alas, Java does not. The common workaround is to make NumberProducer generic as well.
If you want to ensure that T is of a specific subtype you can use
interface Producer<T extends Number>
Not sure what Producer reall is so I have to guess.
Update:
If I understand you correct then I would say, you need to declare an interface which is a Producer. That's simple.
From this interface i would derive a new interface with the respecitve base type.
i.e.:
interface Producer
{
base functions
};
interface Newproducer<T extends Producer>
{
};
Is this what you had in mind?

Generic Types in Interface and Non Generic in Implementation

I wasn't sure how to properly name this question, so if its better suited to be edited, please do so. My question has to do with using generic types in an interface and then forcing the implementation into a specific type. Something like this:
public interface Test<T> {
void testMethod(Object<T> obj);
}
And then instead of allowing a generic object in an implementation of this interface, set the type somehow.
public class TestImpl implements Test<TestObject1> {
#Override
public void testMethod(TestObject1 obj) {
//Do something
}
}
public class Test2Impl implements Test<TestObject2> {
#Override
public void testMethod(TestObject2 obj) {
//Do something
}
}
Except you cannot paramaterize Object and i'm not sure how to set this sort of thing up. Is it even possible? Right now I just use generic Object, but that leaves me being forced to check the type of class being passed in for every single method and/or casting etc etc. It would be so much cleaner if I could just use generics on the interface and then specific classes on the implementation.
public interface Test<T> {
void testMethod(T obj);
}
You were close.
Then you can either write your classes the way you have them if testMethod is specific to the Class being passed in, or ...
public class TestImpl<T> implements Test<T> {
#Override
public void testMethod(T obj) {
//Do something
}
}
Now you can instantiate your class via new TestImpl<TestObject>() or new TestImpl<TestObject2>()

Subclasses of a class that implements a generic interface

I'm working with Google Web Toolkit, and I'm having problems implementing a generic interface. I'm not really familiar with generics, doing an upgrade on someone else's code here.
Here's what I want to do: I want to have an implementation of a generic callback interface that does some logging, and then subclass that implementation in order to handle specific callback scenarios.
The interface is something like this:
public interface AsyncCallback<T> {
void MethodFromAsyncCallback(T result);
}
The abstract and concrete implementations look something like this:
class CallbackBase implements AsyncCallback<Object> {
public abstract void doStuff(Object result);
public void MethodFromAsyncCallback(Object result) {
// IMPORTANT STUFF
// here are things I would like to do for all callbacks, hence the superclass.
// Then we do the subclass specific things.
doStuff(result);
}
}
class SpecificCallback extends CallbackBase
{
public void doStuff(Object result) {
Integer i = (Integer)result;
// do stuff with i
}
}
The callbacks are required to be fired from
public interface MyServiceAsync {
public void DoSomeThing(AsyncCallback<Integer>);
}
And then it all comes together in a call that looks like this:
MyServiceAsync myService = (MyServiceAsync)GWT.create(MyServiceAsync.class);
myService.DoSomeThing(new SpecificCallback());
And here's where we have a problem!
When the GWT.create() implements the interface I created, it demands that the type given to AsyncCallback is specified (matches a type elsewhere, outside the scope of this question), hence making DoSomething(AsyncCallback<Integer>) an Integer rather than an Object. This is beyond my control.
It complains that DoSomething() takes AsyncCallback<Integer>. I'm giving it something that inherits from something that is an AsyncCallback<Object>. I guess with generics, concepts of inheritance get somewhat broken?
So my question is this:
Either how can I mush this together so that DoSomething() will recognize that that SpecificCallback meets it's requirements,
or how can I structure the relationship between CallbackBase and SpecificCallback so that duplicate code is avoided, but SpecificCallback implements AsyncCallback<Integer> directly?
Thanks.
What I think you need to do is define CallbackBase like this:
abstract class CallbackBase<T> implements AsyncCallback<T> {
public abstract void doStuff(T result);
public void MethodFromAsyncCallback(T result) {
// general stuff (T is a subclass of Object)
doStuff(result);
}
}
Then you want your specific callbacks to be like this:
class SpecificCallback extends CallbackBase<Integer> {
public void doStuff(Integer result) {
// no need to cast
// do stuff with result
}
}
Then your DoSomething method, which accepts an AsyncCallback<Integer>, will accept a SpecificCallback.
(Pedantic sidenote: please start all methods with lowercase letters in Java)
Edit
For what it's worth, I'd suggest changing your design to use composition rather than inheritance. In this case, rather than using an abstract class CallbackBase and extending it, you'd use a concrete implementation of AsyncCallback<T> that might look something like this:
class GeneralCallbackWrapper<T> implements AsyncCallback<T> {
private final AsyncCallback<? super T> delegate;
public GeneralCallbackWrapper(AsyncCallback<? super T> delegate) {
this.delegate = delegate;
}
public void MethodFromAsyncCallback(T result) {
// general stuff here
delegate.MethodFromAsyncCallback(result);
}
}

Categories