Ok so say I'm modelling the following Football Club: All people are Individuals. A Player is a person and therefore extends an Individual. A Member is a person and therefore extends an Individual.
Superclass:
Individual {name, eyeColour}
Subclasses:
Player extends Individual {position}
Member extends Individual {subscription}
Tom is the owner of the Football Club:
Individual i = new Individual("Tom", "Blue")
Bob & Tony are Players:
Player p1 = new Player("Bob", "Green", "Goalkeeper")
Player p2 = new Player("Tony", "Blue", "Striker")
Steve is a Member:
Member m = new Member("Steve", "Brown", 5.00)
Individuals, Players and Members are all persisted to the same Kind (Individual) in the GAE datastore using Objectify.
name eyeColour position subscription ^d Tom Blue [missing] [missing] Individual Bob Green Goalkeeper [missing] Player Tony Blue Striker [missing] Player Steve Brown [missing] 5.00 Member
What if eg Bob decides to become a Member as well as a Player? I want to store is subscription. I can't upcast Bob to an Individual and then downcast to a Member. Java doesn't allow this. I can't create a new Member and copy all the properties of Bob's Player object and store it back with the same id - I'll lose his Position property. I need Bob to be both a Member and a Player in the datstore but NOT in object form (I'm not after multi-inheritance) I still want to get(Player.class,"Bob") and have a Player object or get(Member.class,"Bob") and have a Member object. I won't need an Object that has both the position and subscription properties at the same time.
I also want to avoid this is the datastore:
name eyeColour position subscription ^d Tom Blue [missing] [missing] Individual Bob Green Goalkeeper [missing] Player Bob Green [missing] 10.00 Member Tony Blue Striker [missing] Player Steve Brown [missing] 5.00 Member
because Bob now has data duplication on name and eyeColour which could lead to data inconsistancy.
Any ideas for how to model this?
Also what if Tom becomes a player, or Steve becomes a member?
Individual {name, eyeColour}
MemberRole {individual, position}
PlayerRole {individual, subscription}
It is clear that inheritance is not suitable for your task. For example, someone may play in two different teams or be a member of two different clubs (and your original structure won't allow having more than one football club at all).
What the individuals are, and what roles do they have, are different things. For example, you wouldn't want for some global DB to store your name, your stackoverflow points, your marital status and your occupation all in the same Individual
table.
If Bob decides to become a member, Bob itself doesn't change; its roles do. Bob decided to become a member is still the same good old Bob, it is just he now will be able to do something he was forbidden to earlier.
PS: You are using the term subscription in your answer. That's what your Player is -- a Subscription . Subscription
s is obviously not some specific subset of Individual
s, Subscription
is a completely different entity. Of course, it should know about what Individual
does it belong to, but it is not an Individual
itself.
At the outset I would see everyone as an Individual
, but you want to make certain individuals either a Player
or a Member
or both
. You would need to model this scenario using Interfaces
. As I am not into Java, I would suggest doing something similar to this code:
interface IPlayable {void MakePlayable (string position)};
interface IMembership {void AddMembership (double subscription)};
class Individual implements IPlayable, IMembership{name, eyeColour, IPlayable.MakePlayable(string position), IMembership.AddMembership(double subscription)};
//Usage to make Tom a Player
Individual tom = new Individual("Tom", "Blue");
tom.MakePlayable("GoalKeeper");
//Usage to make Steve a Member
Individual steve = new Individual("Steve", "Brown");
steve.AddMembership(5.00);
//Usage to make Jim both a Player and a Member
Individual jim = new Individual("Jim", "Black");
jim.MakePlayable("Forward");
jim.AddMembership(4.00);
Other than implementing multiple interface scenario, using an interface is also required here, because using a Member class would otherwise make an individual a permanent member of some club, using IMembership interface you can add a
RemoveMembership()
method that would help to remove membership of anIndividual
whenever required in future.
Try this...
Individual be the SuperClass .
Player and Member as Interfaces .
Assume Bob as a Player and also as a Member.
Now..
Bob is a Individual (ie extends Individual )
Bob implements Player and Member Interfaces (ie Bob Plays roles of Player and Member both)
See Entity Relationships in JDO in the GAE documentation:
You can model relationships between persistent objects using fields of the object types. A relationship between persistent objects can be described as owned, where one of the objects cannot exist without the other, or unowned, where both objects can exist independently of their relationship with one another. The App Engine implementation of the JDO interface can model both owned and unowned one-to-one relationships and one-to-many relationships, both unidirectional and bidirectional.
I'd say that you have two "owned" relationships. Player
and Member
both "own" an Individual
.
public class Individual {
Role role;
int position; //empty for MEMBER,filled for PLAYER_MEMBER and PLAYER
int subscription; //empty for PLAYER,filled for PLAYER_MEMBER and MEMBER }
public enum Role { MEMBER,PLAYER,PLAYER_MEMBER; }
So when a switch is done you just change the role and complete the missing field. A validation should be done thought.
make an class Indiviual (name, eyecolor) and create interfaces of Owner, Player, and Member. You will have unique individuals and you keep on adding functionalities to them. Hence you will have a table as you want and the last column will list the different implementations.
Using interfaces is much better than implementing multiple inheritance, and java does this. So, it's best you use this
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.