如果你不能修改基类,那么就没有办法做到涉及泛型。你可以做两件事。一,检查对象的运行时类型,如果它是一个老师做一件事,如果不是另一件事。
public class MyClass extends MyBase {
@Override public <T> Student assign(T object) {
Student student = new Student();
if (object instanceof Teacher) {
Teacher teacher = (Teacher) object;
student.setTeacherName(teacher.getName());
} else {
student.setTeacherName("unknown");
}
return student;
}
}
二,创建MyClass中,其中一个覆盖通用方法在基类,而只是需要教师作为参数的非通用的方法两个单独assign
方法。
public class MyClass extends MyBase {
@Override public <T> Student assign(T object) {
return new Student();
}
public Student assign(Teacher teacher) {
Student student = new Student();
student.setTeacherName(teacher.getName());
return student;
}
}
当方法被调用时,如果在编译时类型是老师,编译器会选择哪种方法更具体的过载:
public class Main {
/**
* Gets a teacher but calls it an Object.
*
* @return an Object that happens to be a Teacher
*/
public static Object getTeacher() {
return new Teacher();
}
public static void main(String[] args) {
/** A Teacher, and is declared as such */
Teacher teacher = new Teacher();
/**
* Some Object, which just so happens to actually
* be a Teacher (but the compiler can't see that)
*/
Object something = getTeacher();
MyClass mc = new MyClass();
Student withTeacher = mc.assign(teacher);
Student withoutTeacher = mc.assign(something);
}
}
不过,我更希望的一个修改MyBase的解决方案。
编辑补充:其实你可以声明第二,更具体的assign
方法是一种通用的方法,像这样:
public <T extends Teacher> Student assign(T object) {
Student student = new Student();
student.setTeacherName(object.getName());
return student;
}
但这真的只是同上面的第二个例子。该方法不会覆盖基类中的方法,它依然依赖编译器在编译时选择更具体的过载,方法签名的删除与第二个示例中的非泛型方法完全相同:
public Student assign(Teacher)
它只是看起来更有点像从基类方法的重写,因为它有一个泛型类型变量和参数被命名为object
,而不是teacher
。但是试着在其上注解一个@Override
注解,编译器会告诉你它不会覆盖或实现超类型的方法。
而且你仍然有挂在其上的通用方法,它没有设置教师姓名,如果你有一个Teacher对象没有被声明为这样,编译器会选择错误的超载,你会挠挠脑袋,想知道为什么,如果对象是老师,老师的名字就没有设置在学生身上。
感谢您的回复。但是如果我不能修改基类呢? – chapstick 2013-02-19 23:54:44