Proper use of generics in abstract java class? - java

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.

Related

why need Generic type then type reasure though we can use Object Pojo

I have code like this:
public class Crate<T> {
private T contents;
public T emptyCrate() {
return contents;
}
public void packCrate(T contents)
{
this.contents = contents;
}
}
Now we know - in the end it will be "converted" to the following code:
public class Crate {
private Object contents;
public Object emptyCrate() {
return contents;
}
public void packCrate(Object contents)
{
this.contents = contents;
}
}
Then why we need to create a generics if i already can create a class like Object Based ?
When people talk about type erasure, they normally focus upon the generic class itself. But there is another important place with generics: the call site.
For example, if you've got this code:
Crate<Integer> intCrate = new Crate<>();
intCrate.packCrate(0);
Integer contents = intCrate.emptyCrate();
Then, when it is compiled, it actually becomes:
Crate intCrate = new Crate();
intCrate.packCrate(0);
Integer contents = (Integer) intCrate.emptyCrate();
// ^ Important! This cast.
i.e. there are casts inserted automatically. Also, implicitly, there is a check that the parameter of packCrate is compatible with Integer, so you couldn't write:
intCrate.packCrate("hello");
Now, you can do this without generics, putting in these casts yourself, but the compiler doesn't help you to know what was put into the Crate. You could write something like this:
Crate crate = new Crate();
crate.packCrate(0);
String contents = (String) crate.emptyCrate();
This will fail at runtime, because the crate contains an Integer, not a String.
Generics just help you not to have to remember what you are allowed to pass to an instance, and what you will get out of it.
You see, java code is translated to bytecode. So why don't you write your programs in byte code? They get translated anyway? Or, to be precise: the JIT compiler will turn most bytecode into machine code at some point. So why do you insist on writing java source code, instead of binary machine code?!
I guess the above questions make my point clear: generics allow you to express intent for human readers. They allow you to write better source code; and they enable the compiler to do certain kinds of checks on your input - as nicely summarized in the other answer by Andy Turner.
That is the whole point of any abstraction that programming languages provide to you: they help you the programmer to create source code that expresses "what needs to be done" in a concise way that makes it easier for human readers to understand what is going on, and why!
It doesn't matter what it will be turned into.
Rather the stage of compilation is important. Generics guarantee type safety at compile type (fixing compile-time errors is much easier than runtime ones).
It also eliminates casts and enables the ability to implement generic algorithms.
All collections in Java are Generics. It's the best example of using Generics. For example you create class List. Which types of objects will it hold? When you create List class, you don't know about which types it will hold, so you use Generics. And when you use Listclass, you say, that you want to put Integers(new List<Integer).
Template parameters in generics are used for compile time safety. Compiler will choke if you write for example:
Crate<Integer> cr;
Object o;
cr.packCrate(o); // compilation error here
It can also declare that any class used as parameter will implement some methods:
Interface I {
void myMethod();
}
class Crate<T extends I> {
private T contents;
...
public void applyMethod() {
contents.myMethod(); // T shall implement myMethod
}
}
In fact everything could be done by explicit casting, but you will get only run time errors while generics allow compile time detection of errors.

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 interfaces and types

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.

Why is the following interface contract not allowed?

I'm thinking about offering a new feature to Java and I would like to ask why have it been restricted by design so far:
public abstract class BodyPart {
abstract public void followBodyPart(BodyPart part);
}
public class Head extends BodyPart{
public void followBodyPart(Body body ) { //Why is this kind of implementation not allowed?
...
}
}
public class Body extends BodyPart{
public void followBodyPart(Head head ) { //and this
...
}
public void followBodyPart(Forearm leftForearm ) { //and also this
...
}
...
}
//Arm, Forearm, etc...
Why is followBodyPart(Body body) in Head not implementing followBody in BodyPart? If it would, the advantages would be clear.
Firstly, the IDE would be able to offer within it's autocomplete feature Body objects as parameters to followBody instead of any other BodyParts objects that Head can not follow.
Secondly, the current version of Body consists of one function and many instanceof's, which could be eliminated.
Finally, generics can help here but not solve the problem, since this code should be ported to Java ME devices.
This question was already asked, in the not appropriate forum as I discovered here
In regards to the answers, I invite you to think different. I understand that anything implementing BodyPart should accept any BodyPart, but: what I want is to be able to say that Head would be able to accept A BodyPart to follow.
Thanks.
The question was also answered in the forum post you linked..
Namely; the interface defines the function should be able to accept anything that implements BodyPart.
By implementing the function in Head to only accept the subclass Body, but not any other subclass; you are violating that contract (since it no longer accepts anything implementing BodyPart).
Interfaces are usually used to provide to "external" code, allowing them to be sure that, whichever implementation of the interface is provided; they can for sure use the functions defined by the interface.
So if this external code gets an BodyPart, it knows it has a function followBodyPart that can accept anything extending BodyPart as argument. That external code will, however, never know that it got Head (or can, after casting it after an instanceof check) and thus cannot know that the interface function will only accept a Body.
By request; say that you provide the BodyPart interface as some kind of program API. In that case, I do not directly need to know what type of BodyPart it is. Now say that I have two of them; received through some functions in your API, for example with the signature: public BodyPart getBody(). The method states it might be a Body I get back; but it could as well be something else (fact is, I don't know!).
According to the BodyPart interface; I can call followBodyPart on the first BodyPart, and pass the second one in as argument. However, the actual Body implementation would not allow this; and there is no way for me to know that.
If you really want different classes to accept different entries; you should either drop the function from BodyPart and just implement it in the subclasses.
By passing those subclasses back from the API; everyone knows what they're talking with, and what it can do (e.g. public Body getBody() and public Head getHead()). Since I then have the actual implementation classes, which have the actual implementation with a certain BodyPart to 'follow', it isn't a problem.
An other option would be - but stated impossible in your question - to use generics; in such case you can define an Interface stating:
public interface Accepts<T extends BodyPart> {
public void followBodyPart(T part);
}
And the API could pass back either the implemented BodyPart, or an Accepts<Head> instance, for example.
(Edit: as I wrote this here, I forgot to keep in mind you cannot implement the same interface more then once with different generic types; so the generic interface method would need the actual implementation to encapsulate objects that can actually handle the calls, making everything even more a mess)
Bonus edit: ofcourse you can also make AcceptsHead, AcceptsArm as interfaces and effectively working around the generics issue :).
I hope this edit clears up why it would be a weird (and bad) idea to have a generic interface (using BodyPart as argument), but only specify specific implementations in the (possibly hidden) implementation classes.
First of all, I'm not quite intuitively understanding your class relationships - they are circular which is already an indication of a bad design. I'm not saying you don't happen to NEED that particular structure - I would just suggest that some refactoring to remove the circularity might ultimately be a better design.
What it looks like you're trying to do is implement a visitor-pattern. But if you have a reference to the base class, it could never trigger the invocation of the specialized methods - e.g. since the compiler can't pick the method you intended, then the runtime is just going to have to do the instance-of switching for you - it would only be syntactic sugar at best (look up scala, they actually do that).
def bodyPart(part:BodyPart) =>
part match {
Head(h) => /* do something with head h */
Foot(f) => /* do something with foot f */
Toe(t) => /* do something with toe t */
}
The other way to solve this is to abstractly noop all possible visitor types:
public class BodyPart { // could have been abstract class
public void followBodyPart(BodyPart part) { }
public void followBodyPart(Head part) { }
public void followBodyPart(Arm part) { }
public void followBodyPart(Foot part) { }
public void followBodyPart(Toe part) { }
}
public class Head { ... /* only implements Head, BodyPart, others error */ }
public class Arm { ... /* only implements Arm, Abdomen, etc */ }
Now the visitor invoker will staticly choose the correct method at compile time. But it needs more plumbing in each implementation because it needs to decide how to properly handle all the other input types. But that's a good thing - it removes ambiguity.

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