Efficiently wiring together data and representation via GUI Control Factories? - java

Lets say I have a class StaticVehicleInformation which holds "static" information about a vehicle, e.g. its type, serial-number or color.
Now I have a tracking application to track driving vehicles and show them on a map. In such a case StaticVehicleInformation is wrapped in a DynamicVehicleEntry<? extends StaticVehicleInformation>, which basically adds "dynamic" information such as currentPosition, speed or currentDriver. At the same time it has a method <T extends StaticVehicleInformation> <T> getStaticVehicleInformation() to return the wrapped static infos.
In my map or basically in any view showing different moving cars, thus mostly dealing with List<DynamicVehicleEntry <? extends StaticVehicleInformation>, I need to distinguish which actual type of vehicle I'm dealing with to show a different icon and so forth. So by having concrete DynamicVehicleEntry classes (DynamicCarEntry extends DynamicVehicleEntry <StaticCarInformation>, DynamicMotorcycleEntry extends DynamicVehicleEntry <StaticMotorcycleInformation>,...) I get different types of live-tracked vehicles, having different static and - if needed - specific "dynamic" attributes (within the subclasses of DynamicVehicleEntry).
Because of my goal to separate Data from UI, I've built a Factory returning different UI-Elements based on the type of DynamicVehicleEntry they should display:
// .... Factory....
public static Node createNewControlFromType(DynamicVehicleEntry <? extends StaticVehicleInformation> entry) {
// from specific to general
if (entry instanceof DynamicCarEntry) {
return new CarControl(entry);
} else if (entry instanceof DynamicMotorcycleEntry) {
return new MotorcycleControl(entry);
} else {
// no concrete UI-Method found, so return a generic Control showing a dummy-icon
// and only the most generic information common to every DynamicVehicleEntry and the wrapped StaticVehicleInformation
return new GenericControl(entry);
}
}
instanceOf smells, and I think type-erasure of generics might also break my neck. Any ideas how I should solve this assuming I cannot modify the Static...Information and Static...Information classes?
Thanks in advance.
UPDATE:
I've done some extensive search on it and did not find any better solution, especially if one cannot modify existing classes, as it would be needed by a Visitor Pattern. As noted in the comments here one can do some reflection magic to do the same, but from my understanding instanceof is "light"-reflection anyway.

Related

Is this a valid case to use instanceof operator?

I am a beginner in Java and OOP in general, and I have a question regarding inheritance in Java.
In my project, I have a class Order that represents a order placed for an asset. I intend to have several classes that extend Order including LimitBuyOrder and LimitSellOrder & the likewise for market orders.
I will also have a class Position, which consists of a pair of orders. In order to determine the kind of Position, I must know which type of Order was entered first. Although the instanceof operator would work in this situation, I feel it is not an appropriate solution. Below is a stripped-down snippet, which may help to illustrate my problem:
class Position {
//Other fields and methods omitted for clarity
public void open(Order o) {
if(o instanceof LimitBuyOrder)
//Set position type to LONG
if(o instanceof LimitSellOrder)
//Set position type to SHORT
}
}
Or should I do something like define methods in Order such as isLimitBuy() & etc, which return false and override them to return true based on which subclass Order is extended by?
class Position {
//Other fields and methods omitted for clarity
public void open(Order o) {
if(o.isLimitBuyOrder())
//Set position type to LONG
if(o.isLimitSellOrder())
//Set position type to SHORT
}
}
Basically, my question is how do I determine the type of a subclass properly? Thanks in advance!
You should aim to encapsulate the behaviour within the types of orders rather than simply using their types externally to switch behaviour.
Add a method to your 'Order' class that does the work and then you do not have to know what type it is at all:
order.openPosition(...);
Let the 'Order' do whatever it needs to do according to its type.
A significant benefit to encapsulation is that you end up having all the order-type-specific behaviour in one place. Abstract parent classes come naturally to provide any common order characteristics. With the code in one place (or at least in a small hierarchy of classes) you can change the behaviour without having to visit code all over your application.

composition-and-forwarding approach for a class with two Lists

I have read Item 16 from Effective Java and
Prefer composition over inheritance? and now try to apply it to the code written 1 year ago, when I have started getting to know Java.
I am trying to model an animal, which can have traits, i.e. Swimming, Carnivorous, etc. and get different type of food.
public class Animal {
private final List<Trait> traits = new ArrayList<Trait>();
private final List<Food> eatenFood = new ArrayList<Food>();
}
In Item 16 composition-and-forwarding reuseable approach is suggested:
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) {this.s = s;}
//implement all interface methods
public void clear() {s.clear();}
//and so on
}
public class InstrumentedSet<E> extends ForwardingSet<E> {
//counter for how many elements have been added since set was created
}
I can implement ForwardingList<E> but I am not sure on how I would apply it twice for Animal class. Now in Animal I have many methods like below for traits and also for eatenFood. This seems akward to me.
public boolean addTrait (Trait trait) {
return traits.add(trait);
}
public boolean removeTrait (Trait trait) {
return traits.remove(trait);
}
How would you redesign the Animal class?
Should I keep it as it is or try to apply ForwardingList?
There is no reason you'd want to specialize a List for this problem. You are already using Composition here, and it's pretty much what I would expect from the class.
Composition is basically creating a class which has one (or usually more) members. Forwarding is effectively having your methods simply make a call to one of the objects it holds, to handle it. This is exactly what you're already doing.
Anyhow, the methods you mention are exactly the sort of methods I would expect for a class that has-a Trait. I would expect similar addFood / removeFood sorts of methods for the food. If they're wrong, they're the exact sort of wrong that pretty much everyone does.
IIRC (my copy of Effective Java is at work): ForwardingSet's existence was simply because you cannot safely extend a class that wasn't explicitly designed to be extended. If self-usage patterns etc. aren't documented, you can't reasonably delegate calls to super methods because you don't know that addAll may or may not call add repeatedly for the default implemntation. You can, however, safely delegate calls because the object you are delegating to will never make a call the wrapper object. This absolutely doesn't apply here; you're already delegating calls to the list.

Java - data structure to contain a set of different subclasses of the same superclass

I need to have some sort of data structure that can contain heterogenous subclasses of the same superclass, all of which I have implemented myself.
So far, I am attempting to have an ArrayList<SuperClass> list = new ArrayList<SuperClass>();
and then, I am assuming I will be able to cast each slot of list into either of the subclasses, but this is not working out so well.
I need an efficient way to do the aforementioned.
Thanks!
You can do it with any data structure that exists, I would recommend a List or a Set. For instance:
Collection<Super> supers = new ArrayList<Super>();
Now when you say this:
I am assuming I will be able to cast each slot of list into either of
the subclasses,
That is an invalid assumption. The collection will hold any object that extends Super however you cannot arbitrarily cast each element into whatever you want. You would need to do an instanceof test on each element if you are looking for that type of functionality, example follows:
for(Super currentSuper : supers)
{
if(currentSuper instanceof SubA)
{
SubA subA = (Suba) currentSuper);
// do stuff with subA
}
else if(currentSuper instanceof SubB)
{
SubB subB = (SubB) currentSuper);
// do stuff with subB
}
}
Scope as need be.
Now on the point of Vlad:
and much better design would be not to test what the actual class is,
but just to call a virtual method, which will do the right thing in
any case
If you can guarantee the functionality of all potential sub-classes and have no issues with people overriding your classes (in the event you haven't marked them final) you do not need to do the instance of test. Instead your code could be as simple as:
for(Super currentSuper : supers)
{
currentSuper.doSomethingNifty();
}

Java multidimensional hash/matrix

I have n classes which either stack or do not stack on top of one another. All these classes extend the same class (CellObject). I know that more classes will be added to this list, and I want to create some kind of way that it is easy to manipulate "stackability" in one place.
I was thinking of creating a matrix, where the row-index is the class on the bottom of the stack and the column index is the class on the top of the stack. The value would be true (or 1) if you can stack top on bottom, false (0) otherwise.
However, my colleague suggests creating n+1 methods called canStack. One general canStack method would switch on an instanceof statement that would direct it into one of the n submethods. Each of the submethods would just answer the question of whether the top object can stack on the bottom object by itself.
I think my solution is more elegant/clean. Is this true? If so, how would I implement it?
I changed objects to classes
Your solution would be shorter. But it has the drawback that if you add a sublcass of CellObject, you could potentially forget to alter your array. Even if you know this should happen, someone else might some day work on the code. Then again, his solution has that same issue.
Now, this is a slightly wild idea, but since you're essentially saying something about classes it feels like a metadata facility is in order. What you could do is define an annotation that states which classes can be stacked onto the annotated class and/or which classes it can stack on.
Something like this:
#interface Stackable {
Class<? extends CellObject>[] stackables(); //Classes that may stack on the annotated one
Class<? extends Cellobject>[] pillars(); //Classes this one can stack on
}
Then you could create an annotation processor that uses this metadata. It could create a configuration file your read in at compile time, or generate some boilerplate code for you. You could generate meta-classes like JPA does for its type-safe query API that say something about the class. Or you could even retain the annotations at runtime to use reflection for finding out what can stack on what, building up your desired array ad-hoc rather than having to code it.
If you use an annotation processor, then maybe it would be safer to use String arrays with canonical class names, since the Class objects might not be available yet at compile time. Its feasibility would also depend on whether all CellObject classes are always in the same compilation run or not.
Using reflection (possible when making sure the annotation has a RetentionType RUNTIME) seems like a viable option here. Check the array; if the corresponding element is null (can be done by using Boolean instead of boolean), do the reflection stuff and fill in that element. Next time you can avoid the reflection overhead, lazily filling the array as needed.
EDIT: forgot to mention, my solution doesn't enforce you to keep the metadata up-to-date either. Also, the complexity could be reduced if the stackability is transitive. That is, A can stack on B and B can stack on C implies A can stack on C.
The matrix approach would scale as O(n2). In contrast, the other approach would scale as O(n), but it would be riskier to maintain.
As an alternative, consider letting an abstract CellObject implement a suitable Stackable interface, but defer the implementation to the n concrete subclass. the compiler will identify missing implementations immediately. See also When an Abstract Class Implements an Interface.
interface Stackable {
boolean canStack(Stackable other);
}
abstract class CellObject implements Stackable {}
class Cell01 extends CellObject {
#Override
public boolean canStack(Stackable other) {
return true; // TODO
}
}
class Cell02 extends CellObject {
#Override
public boolean canStack(Stackable other) {
return true; // TODO
}
}
...
I don't think your matrix concept would be the good way to achieve your goal. You'll end up with a huge matrix that contains every possibilities. Obviously, extracting the information you wish from the matrix will be fairly easy, but maintaining it in the long run might prove to be a painful experience as more CellObject subclasses are being added. The same applies to the n + 1 methods your colleague suggested.
In both cases, everytime you will add a subblass of CellObject, you will have to either go to the class that holds the matrix, create a new row, and a new column for each existing row, and manually specify if this new class can be stacked or not on class x, or add a new method canStackOnNewClassX () to each existing class. Both solutions are bug prone in my opinion (you might easily forget to update your matrix, or enter the wrong information as the code might not be easily readable), there are more elegant ways to handle such kind of problem.
One thing you could do is have a map in your CellObject super class that will hold on your "stackability" information, and provide methods to populate this map and to retrieve if a member of class A can be stacked on a member of class B. Something like this:
public abstract class CellObject
{
private static Map<Class<? extends CellObject>, Map<Class<? extends CellObject>, Boolean>> fullStackabilityMap =
new HashMap<Class<? extends CellObject>, Map<Class<? extends CellObject>, Boolean>> ();
protected static void addStackableOnObjectInformation (Class<? extends CellObject> baseObjectClass, Class<? extends CellObject> objectToStack, boolean canStackOnObject)
{
Map<Class<? extends CellObject>, Boolean> stackableMapForObject = fullStackabilityMap.get (baseObjectClass);
if (stackableMapForObject == null)
{
stackableMapForObject = new HashMap<Class<? extends CellObject>, Boolean> ();
fullStackabilityMap.put (baseObjectClass, stackableMapForObject);
}
stackableMapForObject.put (objectToStack, canStackOnObject);
}
protected boolean isStackableOnObject (CellObject baseObject)
{
Map<Class<? extends CellObject>, Boolean> stackableMapForObject = CellObject.fullStackabilityMap.get (baseObject.getClass ());
if (stackableMapForObject == null)
{
return false;
}
Boolean canStackOnObject = stackableMapForObject.get (this.getClass ());
return canStackOnObject != null ? canStackOnObject : false; //Assume that the object cannot be stacked if it was not specified
}
}
public class CellObjectA extends CellObject
{
}
public class CellObjectB extends CellObject
{
static
{
addStackableOnObjectInformation (CellObjectB.class, CellObjectA.class, true);
}
}
public class CellObjectC extends CellObject
{
static
{
addStackableOnObjectInformation (CellObjectC.class, CellObjectA.class, true);
addStackableOnObjectInformation (CellObjectC.class, CellObjectB.class, true);
}
}
The creation of fullStackabilityMap in CellObject seems complicated, due to Java's lack of diamond operator in Java 6, but it could be simplified if you wrote a utility method that creates maps, or use Guava.
So, in this example, CellObjectC instances would not be stackable over kind of objects; CellObjectB instances could be stacked on CellObjectC objects only, and CellObjectA could be stacked on either CellObjectB or CellObjectC objects.
The only work you would have to do each time you add a new class is to update the static initializers of your existing classes to make sure this new class is accounted for. The advantages of this solution are:
You only have to specify which kind of object can be stacked on which kind of object. No need to fully initialize a matrix with all possibilities.
You can ask an object directly if it can be stacked on any kind of object, rather than having to statically poll an external class, which to me is easier to maintain, and generates cleaner code.
You do not have to maintain n+1 methods that will tell you with object A can be stacked on object B, which would be a total nightmare if you end up with a significant number of CellObject subclasses.

Subclassing a generic type, returning instances of the subclass from a method in another class

It was such a simple, brilliant idea. Use the power of Java 5.0 enumerated types to encode details of a data dictionary (attribute name, type, range, units, etc.) and create a type-safe system for setting and reading attribute values (i,.e., attribute AAH is short, ACC is enumerated and should only accept the values ACC001, ACC002, ACC003, etc.).
The hitch is that different attributes have different types (integer, float, text, enumerated), and the behaviors for each type are different. So I create a base class with a type parameter and some abstract methods:
public abstract class GsAttributeValueBase<T extends Comparable<T>> {
protected T m_value;
...
public GsAttributeValueBase(...) {..}
...
public abstract void SetValue(T value) throws IllegalArgumentException;
public T GetValue() { return m_value; }
// etc., etc., etc
}
I then subclass this for each type (basically, I'm trying to fake partial specialization):
public class GsAttributeValueShort extends GsAttributeValueBase<Short> {...}
public class GsAttributeValueLong extends GsAttributeValueBase<Long> {...}
public class GsAttributeValueEncoded extends GsAttributeValueBase<GsAttributeEncodedValueEnum> {...}
...
So far so good. Now I want to basically create a factory method in the attribute enumeration type to return an instance of one of the above subtypes (since each attribute knows its type and range), something like
public GsAttributeValueBase<? extends Comparable<?>> CreateInstance()
{
switch(m_format)
{
case SHORT: return new GsAttributeValueShort(...);
case LONG: return new GsAttributeValueLong(...);
case ENCODED: return new GsAttributeValueEncoded(...);
...
}
}
and call the method as:
GsAttributeValueShort = GsAttributeEnum.AAH.CreateInstance();
This is where I hit a brick wall; I get an incompatible types error on the order of
found : GsAttributeValueBase<capture of ? extends java.lang.Comparable<?>>
required: GsAttributeValueShort
I've tried roughly a dozen permutations on the declaration of CreateInstance() so far (it can't be static, since it relies on information specific to the enumeration instance). I'm about to tear my hair out at this point; I've wasted several days going down this rabbit hole, and need to either get this working today or punt altogether.
I really want to make this work; I think it would be valuable to not just this project but other projects going forward. But Java generics don't behave like C++ templates (something that's been driven home with a vengeance over the past week), and I know I'm missing something vital here, but I can't see what it is.
EDIT
I can't make this work the way I'm envisioning in my head and I've burned too much time on it. Thanks for the suggestions, but I'm going to go ahead and close this down.
EDIT 2
Oh. I can't close my own question. Oh well.
What about:
public <T extends Comparable<T>> GsAttributeValueBase<? super T> CreateInstance() {
...
}
Just use a map and my TypeSafeMap pattern.
Some thoughts on Generics: Generics are meant to make collections type safe. They aren't really intended for complex things like building type-safe classes at runtime. So be mindful and use your tools so that they don't become a burden. If a cast works and you don't understand how the generic construct works (even if you just wrote it), use the cast. Just imagine coming back to this code in half a year and having to fix it.

Categories