This is related to java generic wild card. I need to understand how this happen and need solution.
Ex : I have a interface names Processer.
public interface Processer {
void process(P parent, X result);
}
I want to makes P as wildcard. but it not allowed to use wildcard ( ? ) when defining.
When I implement this interface and let IDE to generate implemented methods it generate as follow.
public class FirstProcesser implements Processer {
@Override
public
void process(P parent, String result) {
}
}
I want to modify this implementation as this.
public class FirstProcesser implements Processer {
@Override
public void process(User parent, String result) {
}
}
But it gives compile errors that FirstProcesser should be abstract or implement all the abstract methods.
I need to know why this is happening and a solution.
解决方案
Overriding
You can't override a method
(generic or not)
with one that takes a narrower parameter type.
If you could, it would be impossible for the compiler to tell whether any given method call would be
(future tense)
legal.
An example without any generics at all, which will fail with exactly the same error:
public class X {
public void f(Object o) {
}
}
class Y extends X {
@Override
public void f(String s) {
}
}
Compiling this fails with:
X.java:8: error: method does not override or implement a method from a supertype
@Override
^
1 error
If it were legal, then it would be impossible to reliably compile even very simple methods like:
public static void f(X x) {
x.f(5);
}
If x were an actual X object, that code would work fine, but if x were a Y subtype, it would fail, because 5 is not a String.
This is why the above definition of Y.f is not allowed to override X.f.
By changing FirstProcesser to accept only User objects, you are causing the same problem.
Chain of Responsibility
The
chain of responsibility pattern on Wikipedia
doesn't look much like what you're trying to build.
I can think of two things you might be trying to do...
1.
If the parent parameter is supposed to be the previous handler in the chain, then it should be of type Processer:
public interface Processer {
void process(Processer parent, X result);
}
class StringProcesser implements Processer {
@Override
public void process(Processer parent, String result) {
}
}
2.
If the type of parent is part of the decision-making process, each handler should store a collection of the Class objects it can handle.
The process method should then see if parent.getClass() is in that collection.
A partial definition might look something like:
public interface Processer {
void process(Class> parent, X result);
}
class StringProcesser implements Processer {
private Set> classes = new HashSet>();
public StringProcesser(final Iterable> classes) {
for (final Class> c : classes) {
this.classes.add(c);
}
}
@Override
public void process(Class> parent, String result) {
if (this.classes.contains(parent)) {
System.err.println("Handling...");
System.out.println(result);
return;
}
System.err.println(
"Can't handle. Try next Processer."
);
// ...
}
}
Note that where the generic type parameter and where the wildcard > show up depends on what you're trying to do.
PS: "Processer" should be spelled "Processor".