How to use generics with multiple coupled objects? - java

So I'm having trouble wrapping my head around the proper design for this.
My application has two key objects that control state, that need to interact with one another: ItemList, ItemState. These each rely on a generic ITEM_TYPE so they can function in different contexts. They are also abstract to allow for ITEM_TYPE-dependent behavior.
Both pieces need to know the generic type, but moreover, since they talk to one another, they need to know the generic types of one another. (An ItemList< String > instance needs to know that its ItemState field is an ItemState< String > and vice versa).
My current solution works, but it seems awful. There has to be a better way. This is what I'm doing now:
public abstract class ItemState<
ITEM_TYPE,
STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>,
LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> {
}
public abstract class ItemList<
ITEM_TYPE,
STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>,
LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> {
}
Then an implementing class might look like:
class StringState extends ItemState<String, StringState, StringList> {
}
class StringList extends ItemList<String, StringState, StringList> {
}
Note that for ItemState, STATE_TYPE is a reference back to the implementing class, and likewise for ItemList/LIST_TYPE.
Really my problem would be solved if I just make ItemState an inner class of ItemList since there would be an implicit binding and they could share generic declarations, but both classes are so large and standalone, that I would prefer not to do this.
Any suggestions?
Edit: As a counter-example to a comment:
public abstract class ItemState<ITEM_TYPE> {
public abstract ItemList getItemList();
public void doSomething() {
// This should not compile because abstract super class has
// no idea what the generic type of getItemList() is
ITEM_TYPE item = this.getItemList.getItem();
}
}
Edit 2: I think the best solution I could think of was just to make ItemList/ItemState inherit one way or the other so they can function as the same class. I don't love this solution because it overrides separation of concerns, but it makes the generics a lot more manageable.
Sidenote: my actual applicaiton had this problem with 4 intertwined classes, I just used 2 for simplicity. In actuality the generics were so bad they were incomprehensible and hard to refactor (about 4 entire lines of just generic declarations for each class). I've now made these 4 classes into a vertical inheritance hierarchy
JM Yang's solution is pretty good

I think you may just reference to generic type ITEM_TYPE when declaring these 2 classes.
I'm able to compile below code with no errors.
public abstract class ItemList<ITEM_TYPE> {
public abstract ItemState<ITEM_TYPE> getState();
public abstract ITEM_TYPE getItem();
}
public abstract class ItemState<ITEM_TYPE> {
public abstract ItemList<ITEM_TYPE> getItemList();
public void doSomething() {
ITEM_TYPE item = getItemList().getItem();
System.out.println(item);
}
}
public class StringList extends ItemList<String> {
#Override
public StringState getState() {
return new StringState();
}
#Override
public String getItem() {
return "";
}
}
public class StringState extends ItemState<String> {
#Override
public StringList getItemList() {
return new StringList();
}
}

Related

Specializing method arguments in subclasses in Java

Consider the following situation:
public abstract class AnimalFeed{
}
public class FishFeed extends AnimalFeed{
}
public class BirdFeed extends AnimalFeed{
}
public abstract class Animal{
public void eat(AnimalFeed somethingToEat)
}
Now I would like to define a class "Bird" extending "Animal" being sure that when the bird eats, it eats only BirdFeed.
One solution would be to specify a sort of contract, in which the caller of "eat" must pass an instance of the appropriate feed
public class Bird extends Animal{
#Override
public void eat(AnimalFeed somethingToEat){
BirdFeed somethingGoodForABird
if(somethingToEat.instanceOf(BirdFeed)){
somethingGoodForABird = (BirdFeed) somethingGoodForABird
}else{
//throws error, complaining the caller didn't feed the bird properly
}
}
}
Is it acceptable to delegate the responsibility of the parameter to the caller? How to force the caller to pass a specialization of the parameter? Are there alternative design solutions?
You'd need to add a type variable to the class:
public abstract class Animal<F extends AnimalFeed> {
public abstract void eat(F somethingToEat);
}
Then you can declare your subclasses as wanting a particular type of AnimalFeed:
public class Bird extends Animal<BirdFeed> {
public void eat(BirdFeed somethingToEat) {}
}
public class Fish extends Animal<FishFeed> {
public void eat(FishFeed somethingToEat) {}
}
What you are asking for doesn't make sense from an theoretical point of view.
Restricting a method parameter violates the Liskov Substitution Principle.
The idea there: any occurance (usage) of some base class object must be able to deal with some sub class object, too.
A more simple example: when your base interface goes:
void foo(Number n)
then you must not do
#Override
void foo(Integer i)
in a subclass. Because all of a sudden, a caller
someObject.foo(someNumber)
would run into ugly ugly problems when someObject is of that derived class; which only accepts Integers, but not Numbers.
In other words: good OO design is much more than just writting down A extends B. You have to follow such rules; or you end up with systems are already broken on a conceptual point!
And for the record: it is theoretically valid to widen method parameters (in general, but in Java); and it is also ok to restrict the return types of methods (because these changes can not break client code; and that even works in Java).
Long story short: the answer here is too change your design; for example by using Generics and dependent interfaces to somehow create a relationship between the Animal and the Feed class hierarchy.

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);
}

Why its not necessary to have abstract classes to have abstract method [duplicate]

Can have an abstract class implementing all of its methods-- with no abstract methods in it.
Eg.:
public abstract class someClass {
int a;
public someClass (int a) { this.a = a; }
public void m1 () { /* do something */ }
private void m2 () { /* do something else */ }
}
What's the advantage, if any, of having such an abstract class compared to having the same class as a concrete one instead?
One i can think of is that, when i declare it as abstract, it won't be instantiated.
however, i can have the same effect by making it concrete and its constructor(s) private.
TIA.
//==================
EDIT: One other use I can think of:
it may be extending another abstract class or implementing an interface without implementing that class's abstract methods-- although it is implementing all methods of its own. for whatever it' worth.
It has a conceptual meaning: this class has a behaviour which makes no sense on its own.
Granted, it's difficult to imagine such a scenario without well-defined extension points (i.e. abstract methods), but occasionally it will be a reasonably accurate model of your problem.
You can have something like this:
public abstract class ObjectWithId {
private final String id;
public ObjectWithId( String id ) {
this.id = id;
}
public final String getId() {
return id;
}
}
And then you can extend it to declare different types of objects that have ids. Here you have a fully specified and implemented behaviour but no restriction on any other behaviours subclasses may exhibit.
Note though that a much neater way to model the same thing is to use composition instead of inheritance.
public final class ObjectWithId<T> {
private final String id;
private final T ob;
public ObjectWithId( String id, T ob ) {
this.id = id;
this.ob = ob;
}
public String getId() {
return id;
}
public T getObject() {
return ob;
}
}
But before generics were introduced (up to Java version 1.4), this wouldn't have been as elegant and obviously better than the abstract class solution because you'd have had to trade in type safety.
you can declare to implement an interface and don't provide implementation and then each child implicitly gets interface extended
you prevent to create instance of this class
you in future provide common implementation to all children
As you pointed out, you can prevent the class from being instantiated by making it's constructor private. Othere than that, there is no benefit whatsoever. This is probably supported just to provide language completeness.
We generally use Abstraction concept with inheritance
Consider using abstract classes if any of these statements apply to
your situation:
You want to share code among several closely related classes.
To answer your question,
Why declare a class with concrete methods Abstract?
One possible reason is to support inheritance without actually creating objects
Assume you have two classes one Abstract and other Concrete
Abstract class : AbsClass
abstract class AbsClass {
int a = 5;
//Constructor
public AbsClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
and
Concrete class : ConcreteClass
class ConcreteClass {
int a = 10;
//Made the constructor Private to prevent from creating objects of this class
private ConcreteClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
The above two classes should function similarly (?) Until you try to Subclass them
class AbsImplementer extends AbsClass {
//Works fine
}
class ConcImplementer extends ConcreteClass {
//Compilation Error Implicit super constructor ConcreteClass() is not visible
}
The practical difference is that you can't create an instance of it. You would have to subclass it and create an instance of the subclass.
As to WHY you would want to do this, in practice ... I'm hard pressed to think of a good reason. You could say that the class is only meaningful if someone creates a subclass that implements some function. But then why not make that function abstract in the super-class?
I wouldn't rule out the possibility that someone might come up with some example where this makes sense, but I can't think of one. Just because it's possible to write a piece of code and that code compiles successfully doesn't mean that that it makes sense. I mean, I can write "total_price = item_price * zip_code + customer_height_in_cubits - 7.879", but that doesn't mean such a line of code would be meaningful.
Well assume that you don't care whether the methods of the abstract class are implemented or abstract, but by design it has to be abstract so that when someone extends it, they have to add more methods or override the existing ones or use as is. If they don't want to override the methods then the default behavior is already provided in that abstract class.
In this abstract class, the only criteria you enforce is - one simply cannot instantiate that class and they have to have their only version of class before using it.
So in general, abstract class with few or all methods being implemented, is much better than having an interface which has no methods implemented at all. This is based on the assumption that you are using it as a single inheritance.
Consider something similar to the NVI pattern (not sure what you'd call it in Java):
public abstract class A {
public final void doSomething() {
System.out.println("required");
doOptional();
}
protected void doOptional() {
System.out.println("optional");
}
}
public class B extends A {
#Override
protected void doOptional() {
System.out.println("overridden");
}
}
For your public API, you only expose a public final method which cannot be overridden. It performs some required work inside there and an optional method. When extending this class, you can only override doOptional().
Calling B.doSomething() will always print "required" before it proceeds.
Since doOptional() is not abstract, there's no purely code reason that class A needs to be abstract. But it might be desired for your particular project. For example, a base service that is always extended into specific sub-projects.
This can be useful for cases when the classes derived from the abstract base class must have some behaviour that is different from each other but that behaviour can not be abstracted as residing within a method that has the same signature for all the classes. Being unable to share a signature can occur if the different behaviour requires methods that are passed different primitive types. Because they use primitive types you can not use generics to express the similarity.
An abstract base class without any abstract methods is acting a bit like a marker interface, in that it is declaring that implementing classes must provide some behaviour without having that behaviour encapsulated within a new method with a signature that is the same for all implementations. You would use an abstract base class rather than a marker interface when the implementing classes have some behaviour in common, especially if the base class can implement it for the derived classes.
For example:
abstract class Sender {
protected final void beginMessage() {
...
}
protected final void endMessage() {
...
}
protected final void appendToMessage(int x) {
...
}
}
final class LongSender extends Sender {
public void send(int a, int b, int c) {
beginMessage();
appendToMessage(a);
appendToMessage(b);
appendToMessage(c);
endMessage();
}
}
final class ShortSender extends Sender {
public void send(int a) {
beginMessage();
appendToMessage(a);
endMessage();
}
}
It can be useful if you consider it an utility class.

What's the point in having an abstract class with no abstract methods?

Can have an abstract class implementing all of its methods-- with no abstract methods in it.
Eg.:
public abstract class someClass {
int a;
public someClass (int a) { this.a = a; }
public void m1 () { /* do something */ }
private void m2 () { /* do something else */ }
}
What's the advantage, if any, of having such an abstract class compared to having the same class as a concrete one instead?
One i can think of is that, when i declare it as abstract, it won't be instantiated.
however, i can have the same effect by making it concrete and its constructor(s) private.
TIA.
//==================
EDIT: One other use I can think of:
it may be extending another abstract class or implementing an interface without implementing that class's abstract methods-- although it is implementing all methods of its own. for whatever it' worth.
It has a conceptual meaning: this class has a behaviour which makes no sense on its own.
Granted, it's difficult to imagine such a scenario without well-defined extension points (i.e. abstract methods), but occasionally it will be a reasonably accurate model of your problem.
You can have something like this:
public abstract class ObjectWithId {
private final String id;
public ObjectWithId( String id ) {
this.id = id;
}
public final String getId() {
return id;
}
}
And then you can extend it to declare different types of objects that have ids. Here you have a fully specified and implemented behaviour but no restriction on any other behaviours subclasses may exhibit.
Note though that a much neater way to model the same thing is to use composition instead of inheritance.
public final class ObjectWithId<T> {
private final String id;
private final T ob;
public ObjectWithId( String id, T ob ) {
this.id = id;
this.ob = ob;
}
public String getId() {
return id;
}
public T getObject() {
return ob;
}
}
But before generics were introduced (up to Java version 1.4), this wouldn't have been as elegant and obviously better than the abstract class solution because you'd have had to trade in type safety.
you can declare to implement an interface and don't provide implementation and then each child implicitly gets interface extended
you prevent to create instance of this class
you in future provide common implementation to all children
As you pointed out, you can prevent the class from being instantiated by making it's constructor private. Othere than that, there is no benefit whatsoever. This is probably supported just to provide language completeness.
We generally use Abstraction concept with inheritance
Consider using abstract classes if any of these statements apply to
your situation:
You want to share code among several closely related classes.
To answer your question,
Why declare a class with concrete methods Abstract?
One possible reason is to support inheritance without actually creating objects
Assume you have two classes one Abstract and other Concrete
Abstract class : AbsClass
abstract class AbsClass {
int a = 5;
//Constructor
public AbsClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
and
Concrete class : ConcreteClass
class ConcreteClass {
int a = 10;
//Made the constructor Private to prevent from creating objects of this class
private ConcreteClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
The above two classes should function similarly (?) Until you try to Subclass them
class AbsImplementer extends AbsClass {
//Works fine
}
class ConcImplementer extends ConcreteClass {
//Compilation Error Implicit super constructor ConcreteClass() is not visible
}
The practical difference is that you can't create an instance of it. You would have to subclass it and create an instance of the subclass.
As to WHY you would want to do this, in practice ... I'm hard pressed to think of a good reason. You could say that the class is only meaningful if someone creates a subclass that implements some function. But then why not make that function abstract in the super-class?
I wouldn't rule out the possibility that someone might come up with some example where this makes sense, but I can't think of one. Just because it's possible to write a piece of code and that code compiles successfully doesn't mean that that it makes sense. I mean, I can write "total_price = item_price * zip_code + customer_height_in_cubits - 7.879", but that doesn't mean such a line of code would be meaningful.
Well assume that you don't care whether the methods of the abstract class are implemented or abstract, but by design it has to be abstract so that when someone extends it, they have to add more methods or override the existing ones or use as is. If they don't want to override the methods then the default behavior is already provided in that abstract class.
In this abstract class, the only criteria you enforce is - one simply cannot instantiate that class and they have to have their only version of class before using it.
So in general, abstract class with few or all methods being implemented, is much better than having an interface which has no methods implemented at all. This is based on the assumption that you are using it as a single inheritance.
Consider something similar to the NVI pattern (not sure what you'd call it in Java):
public abstract class A {
public final void doSomething() {
System.out.println("required");
doOptional();
}
protected void doOptional() {
System.out.println("optional");
}
}
public class B extends A {
#Override
protected void doOptional() {
System.out.println("overridden");
}
}
For your public API, you only expose a public final method which cannot be overridden. It performs some required work inside there and an optional method. When extending this class, you can only override doOptional().
Calling B.doSomething() will always print "required" before it proceeds.
Since doOptional() is not abstract, there's no purely code reason that class A needs to be abstract. But it might be desired for your particular project. For example, a base service that is always extended into specific sub-projects.
This can be useful for cases when the classes derived from the abstract base class must have some behaviour that is different from each other but that behaviour can not be abstracted as residing within a method that has the same signature for all the classes. Being unable to share a signature can occur if the different behaviour requires methods that are passed different primitive types. Because they use primitive types you can not use generics to express the similarity.
An abstract base class without any abstract methods is acting a bit like a marker interface, in that it is declaring that implementing classes must provide some behaviour without having that behaviour encapsulated within a new method with a signature that is the same for all implementations. You would use an abstract base class rather than a marker interface when the implementing classes have some behaviour in common, especially if the base class can implement it for the derived classes.
For example:
abstract class Sender {
protected final void beginMessage() {
...
}
protected final void endMessage() {
...
}
protected final void appendToMessage(int x) {
...
}
}
final class LongSender extends Sender {
public void send(int a, int b, int c) {
beginMessage();
appendToMessage(a);
appendToMessage(b);
appendToMessage(c);
endMessage();
}
}
final class ShortSender extends Sender {
public void send(int a) {
beginMessage();
appendToMessage(a);
endMessage();
}
}
It can be useful if you consider it an utility class.

Is it possible to write a method that returns a class object of T?

If I have a base class such that
public abstract class XMLSubscription <T extends XMLMessage>
Is it possible to write a method in XMLSubscription that returns a class object of T?
The only possible solution that I came up with is to have each descendant of XMLSubscription have a method like:
public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage>
{
public Class <XMLStatusMessage> getExpectedMessageType()
{
return XMLStatusMessage.class;
}
}
Unfortunately - and yes, this is due to type erasure - there is no way to return the Class object without providing it at runtime somehow.
Fortunately this is not usually too difficult. Here's how I've typically done this / seen it done:
public abstract class XMLSubscription <T extends XMLMessage> {
private Class<T> messageType;
protected XMLSubscription(Class<T> messageType) {
this.messageType = messageType;
}
public Class<T> getExpectedMessageType() {
return this.messageType;
}
}
public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage> {
public XMLStatusSubscription() {
super(XMLStatusMessage.class);
}
}
As you guessed, T is erased by the compiler. When you instantiate the object it has no idea that's it's supposed to deal with XMLStatusMessage objects. Your base class would define the following template method, and 1.5's covariant return types would keep the compiler happy with the concrete subclasses:
public Class<T> getExpectedMessageType()
There is one meta-comment: this looks a lot like procedural code, where something calls getExpectedMessageType() and then takes action based on the return type. This might be better implemented using a Visitor pattern, with the visitor implementing "doSomething" methods for each of the subclasses of XMLMessage.

Categories