generics and inheritance question
I have three classes:
public abstract class fileHandler<Key extends Object, Value extends Object> {
}
public A extends fileHandler<String, String[]> {
}
public B extends fileHandler<String, String> {
}
Now in my main function i do something like this:
fileHandler file= null;
If (<condition>) {
fileHandler = new A();
} else
fileHandler = new B():
}
But this gives 2 compile time errors:
- Cannot convert A to fileHandler
- Cannot convert B to fileHandler
How can I get rid of these errors as I don't get this error if base class is not generic.
Update:
My class hierarchy is:
class fileHandler<Key, Value> { }
class A extends fileHandler<String, String[]> { }
class B extends fileHandler<String, String> { }
- class C that calls function
gen(object of A)
or - class D that calls function
gen(object of B)
. - both C and D are derived from abstract class E.
Now how should I define these functions in C and D and E:
I gave the following:
E:
public abstract void gen开发者_开发技巧 (fileHandler A) throws exception;
C:
void gen (fileHandler A) throws exception;
D:
void gen (fileHandler A) throws exception;
C, D, and E give error fileHandler is raw type. Reference to generic type fileHandler(Key, Value) should be parameterized.
When you instantiate a generic type with different type arguments, the two instantiations are not type compatible. Different instantiations of a generic type are not type-equivalent in the way that a class that inherits from another class is type-equivalent to that class, even when the type arguments themselves may be related by inheritance. Genericity and polymorphism are two separate language features.
Your code is equivalent to the following:
// Java defaults unspecified type arguments to Object.
fileHandler<Object, Object> file;
if (...) {
// Error: fileHandler<String, String> is not equivalent to fileHandler<Object, Object>
file = new fileHandler<String, String>();
} else {
// Error: fileHandler<String, String[]> is not equivalent to fileHandler<Object, Object>
file = new fileHandler<String, String[]>();
}
If you truly want to isolate a polymorphic interface that is independent of the types used to instantiate your fileHandler class, then I would suggest you use an interface:
interface IFileHandler
{
// If this interface needs to talk about keys and values, it
// does so using only java.lang.Object.
}
public class fileHandler<Key extends Object, Value extends Object>
implements IFileHandler
{
// ...
}
public class A extends fileHandler<String, String>
{
// ...
}
public class B extends fileHandler<String, String[]>
{
// ...
}
IFileHandler file;
if (...) {
file = new A();
} else {
file = new B();
}
I get no compile error... if I fix all the error in your provided code
class fileHandler<Key, Value> {
}
class A extends fileHandler<String, String[]> {
}
class B extends fileHandler<String, String> {
}
then
fileHandler file= null;
if (/* condition */)
{
file = new A();
}
else
{
file = new B();
}
The problem is that you're trying to assign an instance to the class name. You should instead be saying
if (condition) {
file = new A();
} else {
file = new B();
}
"file" is the reference here "fileHandler" is the class name.
Cheers.
How you decide to fix this warning really depends on what you are trying to do and how strictly you want to restrict the allowed types for the parameter of gen()
.
Example 1
Very loose
abstract class E {
public abstract void gen(fileHandler<?,?> A) throws Exception;
}
class C extends E {
@Override
public void gen(fileHandler<?,?> A) throws Exception {}
}
Example 2
Restrict Key
generic to be a String
abstract class E {
public abstract void gen(fileHandler<String,?> A) throws Exception;
}
class C extends E {
@Override
public void gen(fileHandler<String,?> A) throws Exception {}
}
Example 3
You probably want to name the unrestricted type so you can refer to it.
abstract class E {
public abstract <Value> void gen(fileHandler<String,Value> A) throws Exception;
}
class C extends E {
@Override
public <Value> void gen(fileHandler<String,Value> A) throws Exception {}
}
精彩评论