我有两个班级学生和导师。导师基本上是一名具有教师ID的学生(导师扩展学生)。一旦他的合同完成,他就会重新成为一名学生。那么我能以某种方式将他转回他的“前一卷”学生身上吗?
答案 0 :(得分:5)
您真正想要做的是使用composition and not inheritance。将所有对象保持为Student
类型,然后临时为TutorRole
的每个实例分配Student
的行为。
使用此设计,您的Student
类将包含类型TutorRole
的属性(成员变量),您可以在运行时添加或删除它。添加isTutor()
方法可以让您在运行时以清晰简洁的方式确定学生是否是导师。
TutorRole
类将封装作为导师的行为(即方法)。
/*
* The TutorRole can be set at runtime
*/
public class Student {
private String facultyId;
private TutorRole tutorRole = null;
public boolean isTutor() {
return !(tutorRole == null);
}
public void doTutorStuff() {
if(isTutor()) {
tutorRole.doTutorStuff();
}
else {
throw new NotTutorException();
}
}
public void setTutorRole(TutorRole tutorRole) {
this.tutorRole = tutorRole;
}
}
/*
* Ideally this class should implement a generic interface, but I'll keep this simple
*/
public class TutorRole {
public void doTutorStuff() {
// implementation here
}
}
/*
* Now let's use our classes...
*/
Student st = new Student(); // not a tutor
st.setTutorRole(new TutorRole()); // now a tutor
if(st.isTutor()) {
st.doTutorStuff();
}
st.setTutorRole(null); // not a tutor anymore
另一种方法是让Tutor
类包含对Student
对象的引用,但这取决于您将如何与Student和Tutor对象进行交互。想要编码。
答案 1 :(得分:4)
我认为,这会遏制遏制和界面编程。
这个怎么样:
interface IStudent
{
String getName();
int getStudentId();
}
interface IFacultyMember
{
int getFacultyId( );
}
class Student
implements IStudent
{
String name;
int id;
public String getName( ) { return name; }
public int getStudentId( ) { return id; }
}
class Tutor
implements IStudent, IFacultyMember
{
Student student;
int facultyId;
public Tutor ( Student student, int facultyId )
{
this.student = student;
this.facultyId = facultyId;
}
public String getName( ) { return student.getName( ); }
public int getStudentId( ) { return student.getStudentId( ); }
public int getFacultyId( ) { return facultyId; };
}
这样,即使您的学生转到辅导员职位,您的学生仍然是学生。当Tutor的学期到期时,你只需要GC导师记录。
另一方面,学生的记录仍将在中央服务中提供。
答案 2 :(得分:3)
一旦创建了某种类型的实例(例如,Tutor
),那就是实例将拥有的运行时类型。这不能再改变了。
一些替代方案:
Student
提供一些接受另一个Student
实例的构造函数,并复制相关字段。一个所谓的复制构造函数。这样,您就可以根据Student
轻松创建新的Tutor
实例,然后再使用它。FacultyMember
课程,然后将Student
和Tutor
转换为角色。然后,您可以稍后更改FacultyMember
的角色。答案 3 :(得分:2)
你可以投射作为学生的导师,所以你的代码在编译时对待他,但是对象仍然是Tutor,所以调用任何被覆盖的方法将导致Tutor类的版本是调用。
您正在寻找的那种“转换”的唯一方法是创建一个新的Student对象并为其提供Tutor所具有的所有属性。
由于您发现需要进行此转换,因此您可能需要重新考虑类结构。例如,学生和导师可能真的只是个人,每个人都可以扮演学生或教师的角色。
答案 4 :(得分:1)
您无法在Java中更改对象类型。可能最简单的方法是将Tutor中的所有参数克隆到新的Student对象中。
答案 5 :(得分:1)
您可以在Tutor上编写类似TutorToStudent()
的方法,并从您的导师中创建一个新学生。如果你投射你最终仍然是一个导师仍然是一个导师。
在这种情况下,您也可以考虑放弃继承权,并且只有一个标志,表明该学生是否是导师。
答案 6 :(得分:1)
您可以使用与教师完全相同的信息创建一个新学生,并丢弃原始对象。使用复制构造函数Student(Student original)
或Student toStudent()
方法这是快速而肮脏的方式。
而不是让Tutor直接扩展学生,而是将Tutor
特定数据和行为转换为 Decorator 。或者更好的是,制作包含所有人的Tutor
对象的Student
和People
装饰器。这是执行此操作的正确方法之一。
将Tutor
和Student
变为enum Type
并在People
中保留此字段,这比上述更容易但不易扩展,它真的取决于关于导师与学生之间差异的性质。
答案 7 :(得分:1)
没有将他“转换”给学生,他是导师,导师已经是学生。
但是,对此对象的访问进行通用化可能有一些价值,因此您只能使用student方法。 java中有几个习惯用法。
1)您可以在代码中专门使用Student API,但Tutor部分除外。
2)您可以为对象设置“toStudent / toTutor”方法,允许它们返回特定于角色的对象。
//我的偏好 3)您可以使用接口。让Tutor和Student都是接口,并使用接口实现构建对象。如果使用最小接口引用对象,而不是重量级继承模式,则代码将来可能会更好地扩展。