![](/img/trans.png)
[英]Extending abstract method with generic parameter (that must extend generic class) in Java
[英]Extending base class containing abstract generic method in java
我得到一个像这样的基类:
Class MyBase{
public abstract <T> Student assign (T object);
}
我正在扩展如下:
Class MyClass extends MyBase{
@Override
public abstract <T> Student assign (T object){
Student stew = new Student();
......
}
}
我的用途是:传入的对象应该是Teacher类型。 在方法中我想创建一个新的Student,它将通过调用Teacher上的函数来获取一些值。 (例如,stew.setTeacherName = teacher.getName();)然后将Student返回给调用者。
问题:a)我如何获得预期的行为? b)宣布MyBase当前的方式与做MyBase之间的区别是什么? c)我有兴趣知道解决方案,以防我可以更改基类,我不能更改基类。
在此先感谢您的帮助。 此外,如果有任何有用的资源/教程,你可以指出我会很好。 再次感谢。
你不能保证该object
被传递到MyClass
的assign
方法是一个Teacher
,如果MyBase
这样定义。 如果允许修改MyBase
,请执行以下操作:
abstract class MyBase
{
public abstract <T extends Teacher> Student assign (T object);
}
并与您的课程一起扩展:
class MyClass extends MyBase
{
@Override
public <T extends Teacher> Student assign (T object){
Student stew = new Student();
......
}
}
这将保证传入的object
是Teacher
,即使它实际上是Teacher
的子类的实例。
编辑 :修改MyBase
另一种方法。 使泛型参数成为类定义的一部分而不是方法定义。
abstract class MyBase<T extends Teacher>
{
public abstract Student assign (T object);
}
class MyClass<T extends Teacher> extends MyBase<T>
{
@Override
public Student assign (T object)
{
Student stew = new Student();
......
}
}
// Could also do this...
class MyClass2 extends MyBase<Teacher>
{
@Override
public Student assign (Teacher object)
{
Student stew = new Student();
......
}
}
这是Oracle的Java泛型教程 。
如果你不能修改基类,那么实际上并没有一种涉及泛型的方法。 你可以做两件事。 一,检查对象的运行时类型,如果是教师则执行一项操作,如果不是,则执行另一项操作。
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;
}
}
调用该方法时,如果编译时类型为Teacher,编译器将选择该方法的更具体的重载:
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
注释,编译器会告诉你它不会覆盖或实现超类型的方法。
你还有<T>
泛型方法,它不会设置教师名称,如果你有一个未被声明的教师对象,编译器会选择错误的重载,你会抓到你的脑袋想知道为什么,如果对象是教师,那么教师的名字就没有设置在学生身上。
通用方法通常适用于所提供的任何类型,而不是泛型类,它可以专门用于处理具体类型。 这是一种功能性的OO方法。 所以你可能想要的是一个带有T参数的泛型类:
MyBase<T>
有方法使用该参数
public abstract Student assign (T object)
然后专门使用教师
MyClass extends MyBase<Teacher>
用一个
public Student assign (Teacher object)
出于这个原因,我的泛型方法通常是静态的 - 如果实例方法是参数化的,那么类型参数属于类而不是方法是合乎逻辑的。 通常,当然。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.