Reputation: 3885
I have a Student
class and a StudentPool
class defined as follows:
public class Student {
public Student copy () {
return new Student();
}
}
and
public class StudentPool<T extends Student> {
public T copyStudent(T t) {
return t.copy();
}
}
thus, the copyStudent
method cannot be compiled and I have to use un-safe type casting. I cannot understand why Java does regard this as illegal?
Edit: user845279, lcfseth, and Bohemian: I think the following revision to Student may cause the similar scenario, cast a parent class into its child class, but this version can pass compiling:
public class Student {
public <T extends Student> T copy() {
T rv = null;
return rv;
}
}
Edit:
forget the above code: rv
can be either null
or un-safely casted.
Upvotes: 2
Views: 152
Reputation: 55223
Let's say you had a class SmartStudent
that extended Student
, and a StudentPool<SmartStudent>
. In this case copyStudent
should take a SmartStudent
and return a SmartStudent
, however the implementation in Student
isn't doing this - it's only returning a plain Student
instance.
Edit:
In order to implement the pattern you want, you could give Student
and all its subclasses a copy constructor:
public class Student {
public Student(Student other) {
//copy other's Student fields to this instance
}
}
public class SmartStudent extends Student {
public SmartStudent(SmartStudent other) {
super(other);
//copy other's SmartStudent fields to this instance
}
}
and make StudentPool
abstract:
public abstract class AbstractStudentPool<T extends Student> {
public T copyStudent(T original);
}
Each AbstractStudentPool
implementation would call the appropriate copy constructor:
public class SmartStudentPool extends AbstractStudentPool<SmartStudent> {
@Override
public SmartStudent copyStudent(SmartStudent original) {
return new SmartStudent(original);
}
}
Upvotes: 4
Reputation: 425083
The problem is that although Student
returns Student
from copy()
, subclasses would also return Student
... not their own type.
Here's an approach to fix your problem:
public static interface Copyable<T> {
public T copy();
}
public static class Student implements Copyable<Student> {
@Override
public Student copy() {
return new Student();
}
}
public static class StudentPool<T extends Student> {
public T copyStudent(Copyable<T> t) {
return t.copy();
}
}
As a side note, it seems you don't need generics here.
Upvotes: 2
Reputation: 6814
You cannot cast a Parent Class into its Child Class. Implicit cast only works the other way around. Even by using explicit type casting this is highly likely to generate runtime error.
Upvotes: 0