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.
Related
EDIT: This question is not well worded, and the provided answer is correct in a literal sense but did not teach me how to attain what I needed. If you are struggling with the same problem, this is what finally helped me: How to enforce child class behavior/methods when the return types of these methods depends on the child class?
I am trying to implement a basic matrix class from a boilerplate abstract class I wrote. There will be several implementations of this abstract class, each one using a different math library, which I will then test for speed.
Each implementation will hold its data in that library's native matrix data structure. I think this is a use case for generics. At this point I think I've read too many tutorials and watched too many videos, as I just can't seem to figure out all the right places to put the T Notation to make this work correctly.
So my question is twofold:
Have I misused or missed the point of generics?
If not, what is the correct syntax for their use?
I've read the docs plus about three different tutorials and still can't understand.
Here is what I've tried:
public abstract class BaseMatrix<T> {
protected int[] shape;
protected int nrows;
protected int ncols;
protected T data; // <--- Here is the generic data --->
public BaseMatrix(int rows, int cols){
this.nrows = rows;
this.ncols = cols;
this.shape = new int[]{nrows, ncols};
}
public abstract BaseMatrix mmul(BaseMatrix other);
And here is my implementation:
public class ND4JDenseMatrix extends BaseMatrix{
// private INDArray data;
public ND4JDenseMatrix(int rows, int cols) {
super(rows, cols);
this.data = Nd4j.zeros(this.shape); <--- Here is the non-generic data --->
}
#Override
public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
ND4JDenseMatrix result = new ND4JDenseMatrix(nrows, ncols);
result.data = data.mmul(other.data);
return result;
}
The error is: Method does not override method from its superclass.
hold its data in that library's native matrix data structure. I think this is a use case for generics.
Generics serves to link things. You declared the type variable with <T>, and you've used it in, as far as your paste goes, exactly one place (a field, of type T). That's a red flag; generally, given that it links things, if you use it in only one place that's usually a bad sign.
Here's what I mean: Imagine you want to write a method that says: This method takes 2 parameters and returns something. This code doesn't particularly care what you toss in here, but, the parameters must be the same type and I return something of that type too. You want to link the type of the parameter, the type of the other parameter, and the return type together.
That is what generics is for.
It may apply here, if we twist our minds a bit: You want to link the type of the data field to a notion that some specific implementation of BaseMatrix can only operate on some specific type, e.g. ND4JMatrix.
However, mostly, no, this doesn't strike me as proper use of generics. You can avoid it altogether quite easily: Just.. stop having that private T data; field. What good is it doing you here? You have no idea what type that is, you don't even know if it is serializable. You know nothing about it, and the compiler confirms this: There is absolutely not one iota you can do with that object, except things you can do to all objects which are generally quite uninteresting. You can call .toString() on it, synchronize on it, maybe invoke .hashCode(), that's about it.
Why not just ditch that field? The implementation can make the field, no need for it to be in base!
public class ND4JDense extends BaseMatrix {
private ND4JMatrix data; // why not like this?
}
(This code assumes 'ND4JMatrix' is the proper data type you desire here, a thing that can is the internal representation for the data in the ND4J impl).
However, if you must, yeah, you can use generics here. You've type-varred BaseMatrix, and that means all usages of BaseMatrix must be parameterized. That's the part you messed up in your code. If we go with your plan of a type-parameterized BaseMatrix class and a field of type T, the right code is:
public class ND4JDense extends BaseMatrix<ND4JMatrix> {
...
}
I wouldn't, however, do it this way (I'd go with having the impl have the field, much simpler, no need to bother anybody with the generics). Unless, of course, you DO have an actual need for that field and it IS part of BaseMatrix's API. For example, if you want this:
public class BaseMatrix<T> {
public T getData() { return data; }
}
then it starts to make more sense. With that, you can write the following and it'll all compile and work great:
public class ND4JDense extends BaseMatrix<ND4JMatrix> {
...
// no need to write a getData method here at all!
...
}
ND4JDense dense = new ND4JDense();
ND4JMatrix matrix = dense.getData();
But, clearly, this makes no sense if you intend for the ND4JMatrix to remain an implementation detail that users of the BaseMatrix API should probably not be touching.
EDIT: You changed the question on me, later. Now you want the mmul method to take 'self' as argument, effectively: You want the same type to be passed in.
You can sort of do that but it is a little tricky. You need the self-ref generics hack. It looks like this:
public class BaseMatrix<T extends BaseMatrix<T>> {
public abstract T mmul(T other);
}
In practice the only valid value for T is your own class, or at least, that is the intent. This works fine:
public class ND4JDenseMatrix extends BaseMatrix<ND4JDenseMatrix> {
public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
.. impl here ..
}
}
As far as I see, you have two issues in your code:
You're not actually overriding the method of the superclass. What you have created is an overload of method mmul. To correctly override the method, the method signature must match, in particular the input parameter must be the same. It's ok to have a subtype of the return type, as Java support covariant. If you instead put one of its subclass, that is overloading. Hope you get the difference. So the correct signature can be the following:
public BaseMatrix mmul(BaseMatrix other) {
...
}
You have not specified the type T, so the compiler cannot know that by assumption is a subtype of BaseMatrix. it can be any type, even Object for example, so you are going to get "method not found" compilation error.
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.
Let's say you have some Java code as follows:
public class Base{
public void m(int x){
// code
}
}
and then a subclass Derived, which extends Base as follows:
public class Derived extends Base{
public void m(int x){ //this is overriding
// code
}
public void m(double x){ //this is overloading
// code
}
}
and then you have some declarations as follows:
Base b = new Base();
Base d = new Derived();
Derived e = new Derived();
b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works
For the one that does not compile, I understand that you are passing in a double into Base's version of the m method, but what I do not understand is... what is the point of ever having a declaration like "Base b = new Derived();" ?
It seems like a good way to run into all kinds of casting problems, and if you want to use a Derived object, why not just go for a declaration like for "e"?
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java. The way I learned it earlier this summer was, every object has one class, which corresponds to the name of the class following "new" when you instantiate an object, but an object can have as many types as it wants. For example, "e" has type Base, Derived, (and Object ;) ) but its class is Derived. Is this correct?
Also, if Derived implemented an interface called CanDoMath (while still extending Base), is it correct to say that it has type "CanDoMath" as well as Base, Derived, and Object?
I often write functions in the following form:
public Collection<MyObject> foo() {}
public void bar(Collection<MyObject> stuff){}
I could just as easily have made it ArrayList in both instances, however what happens if I later decide to make the representation a Set? The answer is I have a lot of refactoring to do since I changed my method contract. However, if I leave it as Collection I can seamlessly change from ArrayList to HashSet at will. Using the example of ArrayList it has the following types:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
There are a number of cases where confining yourself to a particular (sub)class is not desired, such as the case you have where e.m(8.0);. Suppose, for example, you have a method called move that moves an object in the coordinate graph of a program. However, at the time you write the method you may have both cartesian and radial graphs, handled by different classes.
If you rely on knowing what the sub-class is, you force yourself into a position wherein higher levels of code must know about lower levels of code, when really they just want to rely on the fact that a particular method with a particular signature exists. There are lots of good examples:
Wanting to apply a query to a database while being agnostic to how the connection is made.
Wanting to authenticate a user, without having to know ahead of time the strategy being used.
Wanting to encrypt information, without needing to rip out a bunch of code when a better encryption technique comes along.
In these situations, you simply want to ensure the object has a particular type, which guarantees that particular method signatures are available. In this way your example is contrived; you're asking why not just use a class that has a method wherein a double is the signature's parameter, instead of a class where that isn't available. (Simply put; you can't use a class that doesn't have the available method.)
There is another reason as well. Consider:
class Base {
public void Blah() {
//code
}
}
class Extended extends Base {
private int SuperSensitiveVariable;
public setSuperSensistiveVariable(int value) {
this.SuperSensistiveVariable = value;
}
public void Blah() {
//code
}
}
//elsewhere
Base b = new Extended();
Extended e = new Extended();
Note that in the b case, I do not have access to the method set() and thus can't muck up the super sensitive variable accidentally. I can only do that in the e case. This helps make sure those things are only done in the right place.
Your definition of type is good, as is your understanding of what types a particular object would have.
What is the point of having Base b = new Derived();?
The point of this is using polymorphism to change your implementation. For example, someone might do:
List<String> strings = new LinkedList<String>();
If they do some profiling and find that the most common operation on this list is inefficient for the type of list, they can swap it out for an ArrayList. In this way you get flexibility.
if you want to use a Derived object
If you need the methods on the derived object, then you would use the derived object. Have a look at the BufferedInputStream class - you use this not because of its internal implementation but because it wraps an InputStream and provides convenience methods.
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java.
It sounds like your teacher is referring to Interfaces and Classes as "types". This is a reasonable abstraction, as a class that implement an interface and extends a class can be referred to in 3 ways, i.e.
public class Foo extends AbstractFoo implements Comparable<Foo>
// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();
An example of the types being used in different contexts:
new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection
This is one of the classic problems on object oriented designs. When something like this happens, it usually means the design can be improved; there is almost always a somewhat elegant solution to these problems....
For example, why dont you pull the m that takes a double up into the base class?
With respect to your second question, an object can have more than one type, because Interfaces are also types, and classes can implement more than one interface.
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.
I have an abstract class that implements an interface. I then have several classes that extends that abstract class that are in turn composed of a hierarchy of some objects plus one or more Lists of objects extending the same abstract class, repeated for some levels. In essence,
public interface Bar
public abstract class BarImpl implements Bar
public class Foo extends BarImpl {
private String value1;
private String value2;
private List<Foo2> fooSubs;
public List<Foo2> getFooSubs() {
return fooSubs;
}
}
public class Foo2 extends BarImpl {
private String value3;
private String value4;
private List<Foo3> fooSubs;
public List<Foo3> getFooSubs() {
return fooSubs;
}
}
...etc...
The data in question is actually X12 healthcare claim data for those who are familiar. I've defined a Loop interface to correspond to the various loops that compose the X12 file.
My issues is this - I need to also be able to describe a single transaction, in theory using the same object or some wrapper on that object, where for some specified depth the size of each list of objects is 1.
My first though is/was to add a boolean singleTransaction to the BarImpl abstract class. Each class extending that would then have a check on the addFoo methods to make sure that the object did not grow beyond the single entry. Before converting to FooSingle I would check as well.
public void addFoo(Foo foo) throws FooException {
if (singleTransaction && fooSubs.size() >= 1)
throw new FooException();
else
fooSubs.add(foo);
}
I would also have to remove the setFoo method, so as to prevent an already-populated List from being assigned. Perhaps just make it final...
Does this seem like a reasonable way to go about this? I could then have a SingleBarImpl class that would verify it had a single path down the hierarchy, filter the boolean down, and could then safely assume that there was only one object-per-list for the specified classes. This could then simplify the access to the hierarchy since I no longer needed to worry about multiple list entires.
This feels very ugly is why I raise the question, and I wasn't quite sure what I should search on for an alternative. So I decided to stop lurking, create an account, and throw this out there. So...any ideas? Am I missing some design pattern that makes this much more elegant?
I am not familiar with X12 healthcare claim data and hence can't properly model the domain, but it sounds like you want to use the GOF composite pattern . A "Leaf" implementation class could easily replace your "singleTransaction" flag