OO Class Design Question
Hey everyone,
I have a general OO question. Assume the following:
Person - Holds demographic information and contact information for all people
User - is a person
Teacher - is a person
Now. The same person can be both a teacher and a user. There are some required fields for a user that are not required and may not exist for a teacher. The same is true regarding a user.
I would model this as the following 3 objects:
Person - Superclass
User - Subclass of person
Teacher - Subclass of person.
I am not sure if this is the correct approach. I've been told the correct approach would be using aggregation rather than inheritence. In other words
The Person object contains a User and Teacher object. Doesn't that mean I would need wrappers methods on the Person class for all public methods on the User and Teacher classes? My DBMS is modeled as this:
(simplified)
People
======
PeopleId (int) (not null) (pk)
Name
Address
etc....
User
=====
UserId (int) (not null) (pk)
PeopleId (int) (not null) (fk)
LogonId (VarChar(20)) (not null)
Teacher
=======
TeacherId (int) (not null) (pk)
PeopleId (int) (not null) (fk)
CertNumber (VarChar(25) (not null)
I can't flatten out the People table to be able to handle storing a User and Teacher in the same row because I don't want to complicate the constraints for non-nullable fields and this will make the People table too de-normalized for my prefence.
How would you all go about modeling this simple example? Also consider that there could (read will) be other classes of people added (students, parents, etc...)
Thank you
John D
Try this aproach.
public interface Person{ // defines the comon Interface of a Person
public Role getRoles(String rolename) // hand out the different roles the person can play
public void addRole(String name, Role role);
public void removeRole(String name, Role role);
...
}
public class ConcretePerson implements Person{ // the implementation of basic Person behaviour (handling of name/ DoB and the like,
...
}
public abstract class Role implements Person{ // all calls to the methods of Person get delegated to the ConcretePerson
private ConcretePerson
}
public class Teacher extends Role; // Teacher typical behaviour
public class User extends Role; // user typical behaviour
regards
Spieler
In this case I think that a "Teacher" is not a specialization of a person, neither is a user. I would suggest that "Teacher" inherits from "Occupation" ("Teacher" is an "Occupation"). In the same way a "User" is a kind of "Role". Therefore I would suggest the following classes:
interface Occupation {}
interface Teacher extends Occupation{}
interface Role {}
interface User extends Role {}
class Person implements User {
Vector occupations;
}
Occupation maybe could do as an abstract class as well, but I thought that an occupation more describes aspects than properties. It would also be possible to implement the "Occupation" interface (not the teacher, since what will happen when there's a person that is not a teacher?), but it seems more likely that the "Person" could have no occupation.
/Klas
If you were to create [b]Person[/b], [b]Teacher[/b], and [b]User[/b] interfaces as below you could then create concrete classes based off them. This will allow you to create somebody who is both a [b]Teacher[/b], and a [b]User[/b].
[code]
public interface Person {
// person methods
}
public interface Teacher extends Person {
// teacher-specific methods
}
public interface User extends Person {
// user-specific interfaces
}
[\code]
This will
> allow you to create somebody who is both a
> Teacher, and a User.
>
true but you wil end up with a lot of duplicate code:
you'll have the code for persons three times:
- in User
- in Teacher
- in UserTeacher
all the other code is present at least twice
what happens if you have a different Role or Occupation let's say Mentor continuing your aproach will lead to
the additional classes
Mentor
TeacherMentor
UserMentor
UserTeacherMentor
this would be a really bad usage of inheritance
regards
Spieler
Code duplication is bad. This can be addressed to some degree w/ abstract classes:
public abstract class PersonAbstr implements Person {
// common code
}
public abstract class TeacherAbstr extends PersonAbstr {
// Teacher common code
}
public abstract class UserAbstr extends PersonAbstr {
// User common code
}
But then if you have UserTeacherMentor you can only inherity from one of the abstrs. Will this happen? Is Mentor a Teacher? At this point we need domain knowledge to determine whether we're getting into a mess and what sort of compromises we might need to make in the design. Right now all we know is that we need to go to level 2 (TeacherUser)
Cheers ...
You may want to explore the Role Pattern - see here - http://www.martinfowler.com/apsupp/roles.pdf
I had a far more complex role management situation where a legal Party could on one hand be a Person or a Company, on the other hand they could be an Agent, a Bank, a Client etc.
I went for an adaptation of the role pattern with this - http://jerry.cs.uiuc.edu/~plop/plop97/Proceedings/riehle.pdf