I can't seem to figure out why a method call I'm trying to make doesn't work.
I've looked much around SO before asking this, and while there are (many) threads about similar problems, I couldn't find one that quite fits my problem..
I have the following code:
(in file Processor.java:)
public interface Processor
{
Runner<? extends Processor> getRunner();
}
(in file Runner.java:)
public interface Runner<P extends Processor>
{
int runProcessors(Collection<P> processors);
}
(in some other file, in some method:)
Collection<? extends Processor> processorsCollection = ...;
Runner<? extends Processor> runner = ...;
runner.runProcessors(processorsCollection);
IntelliJ marks the last line as an error:
"RunProcessors (java.util.Collection>) in Runner cannot be applied to (java.util.Collection>)".
I can't figure out whats wrong with what I did, especially since the error message is not quite clear..
any suggestions?
thanks.
Both your collection and your runner allow for anything that extend processor. But, you can't guarantee they're the same.
Collection might be Collection<Processor1> and Runner be Runner<Processor2>.
Whatever method you have that in needs to be typed (I forget the exact syntax, but I'm sure you can find it!)
void <T extends Processor<T>> foo() {
Collection<T> procColl = ...
Runner<T> runner = ...
runner.runProc(procColl);
}
Edit:
#newAcct makes an excellent point: you need to genericize (is that a word?) your Processor. I've updated my code snippet above as to reflect this important change.
public interface Processor<P extends Processor>
{
Runner<P> getRunner();
}
public interface Runner<P extends Processor<P>>
{
int runProcessors(Collection<P> processors);
}
You have not made your situation clear and you're not showing us any of the code of the methods or of how you get the objects, so we don't really know what you're trying to do.
Your code is not type-safe. As #glowcoder mentioned, there is no way of knowing that the parameter of Collection is the same as the parameter of Runner. If you believe they are indeed the same, then that is based on code that you're not showing us (i.e. what happens in "..."?)
You have written Processor's getRunner() method with a return type that has a wildcard parameter. This says when run it will return a Runner with a mysterious parameter that it determines and we don't know. This doesn't make much sense and is probably not what you wanted.
Also depending on what you are doing, the runProcessors method could possibly take a less strict bound. For example, perhaps <? extends P> or even <? extends Processor> if you don't need to modify the collection.
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've been a Java developer since 2011 and usually have no problem in getting the hang of the errors since I've seen them tons of times already. Even this one I've seen a lot and I usually know how to solve it.
However, today I ran into an odd problem which judging by what it means, I can't get my head around what the problem really is.
So I'm a modder, specificly for Minecraft and in this case Bukkit. However that is completly irrelevant for the problem since this is rather something to do with the language itself and not any library made with it.
So the error.
Cannot instantiate the type LinqMap<Integer, ? extends ItemStack>
Usually when I see this, I think it's because the type I'm trying to use, either is an interface, is abstract, or the specified constructors are either private or not defined however some of these do have their own errors, but that's what I usually check.
I also noticed there's a lot of copies of this error over Stack Overflow, however most of them seem to point in the direction of instancing List which is an interface, or some custom class which is abstract. This would be the same, if it wasn't for the fact that I already checked this, and it's not the problem it turns out.
So the piece of code I originally tried to use, looks as follows
HashMap<Integer,? extends ItemStack> stackmap = new LinqMap<Integer,? extends ItemStack>(player.getInventory().all(prototype.getType()));
Now, this was a bit hard to spot, so I tried narrowing it down. I took note of the constructor of LinqMap which takes either no parameters, or a Map<K,V>.
Also want to point out that all returns HashMap<Integer, ? extends ItemStack> in case you wonder what it returns. Anyway, So I tried again with the following code
Map<Integer,? extends ItemStack> map = player.getInventory().all(prototype.getType());
HashMap<Integer,? extends ItemStack> stackmap = new LinqMap<Integer,? extends ItemStack>(map);
This still didn't work, so I tried using the empty constructor which ends up like this
HashMap<Integer,? extends ItemStack> stackmap = new LinqMap<Integer,? extends ItemStack>();
This still ended up in the error, which really surprised me, since the object is a class, it has no modifiers except being public, and both the constructors including the parameter-less one is empty.
So what's the problem here? Why can't I create an instance of a LinqMap when the code clearly allows for it?
Also, here's a small snippet of the class for reference, it's custom made by me and is a port of Linq from C# (not released)
import java.util.HashMap;
import java.util.Map;
public class LinqMap<K,V> extends HashMap<K,V> {
/**
*
*/
private static final long serialVersionUID = 1796259800183459223L;
public LinqMap(final Map<K,V> other) {
for (Map.Entry<K, V> item : other.entrySet()) {
this.put(item.getKey(), item.getValue());
}
}
public LinqMap() {
}
/* ... */
}
In Java, you're not allowed to instantiate wildcard types ? directly. If you're compiling with at least Java 7, then I recommend you simply take advantage of diamond inference:
Map<Integer, ? extends ItemStack> map = player.getInventory().all(prototype.getType());
HashMap<Integer, ? extends ItemStack> stackmap = new LinqMap<>(map);
I have a class hierarchy where cousins share very similar functionality. For example:
Node
Statement
FunctionCallStatement
Expression
FunctionCallExpression
FunctionCallStatement and FunctionCallExpression share a very similar API, but I cannot express that in pure class terms with a single-inheritance hierarchy. So, I've created an IsFunctionCall Interface which both of these implement. I can now declare a method which takes either a FunctionCallStatement or a FunctionCallExpression as follows:
void <T extends Node & IsFunctionCall> doSomething(T node) { ... }
This all works very nicely.
Unfortunately, I've now found myself faced with a rather awkward problem. I have a Node; I know dynamically that it must be either a FunctionCallStatement or a FunctionCallExpression; I need to pass that Node into the doSomething() method above. I cannot find a way to upcast it to an appropriate type.
Right now I'm using a chain of instanceof to determine which class the Node is and to cast it to the appropriate concrete type, but that's butt-ugly. The only other way I know to make this work is to make an IsNode interface and have everything that currently expects a Node expect an IsNode instead; this would allow me to declare a union interface that implements IsNode and IsFunctionCall and let me do away without the generics above. But that's a hell of a lot of work and is still pretty ugly.
Is there an alternative way to do this?
(Note: example above is a simplified version of my actual code.)
Update: I tried the following piece of evil:
#SuppressWarnings("unchecked")
private <S extends Node & IsFunctionCall> S castNode(Node node)
{
return (S) node;
}
and then:
doSomething(castNode(node));
I got some very strange error messages. It would appear that the type inference used to determine the S of castNode() will not match against the T in the declaration of doSomething(); it's using the concrete type only and setting S to Node. Which of course does not match doSomething()'s declared type. Very peculiar.
Update update:
This appears to be a close duplicate of How should I cast for Java generic with multiple bounds?. My situation is slightly different because my bounds include an object and an interface, while the one in the other question has two interfaces, but it's still applicable.
Looks like I need to go and reengineer my entire application. Sigh.
Any admin, feel free to close this as a duplicate...
I think the way out of this, although not exactly elegant, is to have a few overloads for doSomething:
void doSomething(FunctionCallStatement node) ...
void doSomething(FunctionCallExpression node) ...
You are using the interface to flag functionality, how about passing as argument a reference to the FunctionCallInterface which offers access to the function call abstraction?
doSomething won't have to know the actual implementation type as long as it can access the relevant information and call relevant methods on the implementation objects.
public class FunctionCallStatement extends Statement implements FunctionCallInterface {
}
void doSomething(FunctionCallInterface node) {
}
Recently in an answer it was suggested to me that this:
public interface Operation<R extends OperationResult, P extends OperationParam> {
public R execute(P param);
}
Is better than this:
public interface Operation {
public OperationResult execute(OperationParam param);
}
I however can't see any benefit in using the first code block over the second one ...
Given that both OperationResult and OperationParam are interfaces an implementer needs to return a derived class anyway and this seems quite obvious to me.
So do you see any reason the use the first code block over the second one ?
This way you can declare your Operation implementations to return a more specific result, e.g.
class SumOperation implements Operation<SumResult, SumParam>
Though whether this is of any value to your application depends entirely on the situation.
Update: Of course you could return a more specific result without having a generic interface, but this way you can restrict the input parameters as well.
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.