Wic*_*koo 2 java subclass wrapper
假设我有一个班级人员如下:
public class Person {
String name;
int age;
}
Run Code Online (Sandbox Code Playgroud)
和许多子类,例如
public class Student extends Person {
// extra fields and methods
}
public class Teacher extends Person {
// extra fields and methods
}
Run Code Online (Sandbox Code Playgroud)
现在,考虑到对于某些应用程序,我需要为每个 person 实例分配一个整数 id,但我不想扩展接口Person以在其中添加 getId() 和一个用于保存 id 的字段。一个简单的解决方案是使用如下包装器:
public class PersonWrapper extends Person {
public PersonWrapper(Person p, int id) { // assign the id and other fields }
public int getId() { return id; }
}
Run Code Online (Sandbox Code Playgroud)
这样,客户端代码仍然可以使用 Person 接口,并且可以将包装的人视为一个人。这种方法的问题在于 PersonWrapper 是 Person 的子类,而不是 Teacher 或 Student,这样的代码将不起作用:
Teacher t = new PersonWrapper(teacher, 1);
t.giveGrade();
Run Code Online (Sandbox Code Playgroud)
当然,可以为 的所有子类创建具体的包装类型Person,但我想知道是否有更优雅的解决方案。理想的解决方案是这样的:
public class PersonWrapper<T extends Person> extends T
Run Code Online (Sandbox Code Playgroud)
这样任何 PersonWrapper 都是它所包装的类型的子类,但这在 Java 中是不可能的,我怀疑这样的定义在任何语言中都不可能。
在任何情况下,如何在不更改与 person 及其子类一起使用的客户端代码、不为每个子类创建具体包装器的情况下将 id 分配给子类?
包装器不一定需要扩展到它所包装的类。所以,只需使用PersonWrapper<T extends Person>:
public class PersonWrapper<T extends Person> {
T person;
int id;
public PersonWrapper(T person, int id) {
this.person = person;
this.id = id;
}
//getters and setters...
}
Run Code Online (Sandbox Code Playgroud)
此外,一个类只能在编译时从另一个类扩展,因此它不可能同时PersonWrapper从另一个类扩展,这使得您所寻找的内容变得不可能。StudentTeacher
唯一的解决方案是使用cglib等库动态创建代理类。例如,当需要向类动态添加功能(例如为方法或整个类添加事务管理)时,Spring 会为类创建代理。