Reputation: 381
I have a basic assignment to do but am very new to OOP and struggling with it. Other online resources are starting to add to my confusion.
I am required to:
Write code for a class Person. A Person object is to have attributes name, age and address.
Write code for a class Dog. A Dog object is to have attributes name and age.
Give any additional code in the Person and Dog classes that is required to setup a bidirectional association between a Person object and a Dog object. A Person object acts as an owner for a Dog object and the Dog object acts as a pet for the Person object.
Modify your Person class so that a Person object can act as owner for up to 20 Dog objects.
Obviously this is a very simple example.
My code so far:
Person Class :
public class Person
{
// instance variables - replace the example below with your own
private String name;
private int age;
private String address;
/**
* Constructor for objects of class Person
*/
public Person()
{
this.name = name;
this.age = age;
this.address = address;
}
//Set Methods:
public void setName () {
this.name = name;
}
public void setAge () {
this.age = age;
}
public void setAddress () {
this.address = address;
}
//Get Methods:
public String getName () {
return name;
}
public int getAge () {
return age;
}
public String getAddress () {
return address;
}
}
Dog Class:
public class Dog
{
// instance variables - replace the example below with your own
private String name;
private int age;
public Dog()
{
this.name = name;
this.age = age;
}
//Set Methods:
public void setName () {
this.name = name;
}
public void setAge () {
this.age = age;
}
//Get Methods:
public String getName () {
return name;
}
public int getAge () {
return age;
}
}
Main:
public class Main
{
//Blank
}
I know this code is currently useless and doesn't do anything but I am unsure of how to 'associate' the objects & where to do it. The assignment spec specifies a person acts as an 'owner' for the dog.
This is where my problem lies. Setting up the relationship between the objects.
Upvotes: 7
Views: 21167
Reputation: 13535
The main problem here is consistency: if a Dog d1 is a pet for a Person p1, then p1 must be owner of d1, and vice versa. If, as many suggested, we have 2 methods (Person.addDog()
and Dog.setOwner()
), then a user can easily make a mistake and fail to call both methods (or call with wrong arguments). Since a Dog can have only one owner, a simple and safe interface would be using single method Dog.setOwner(Person p)
, where p
may be null if we want the dog to have no owner. This method, besides setting the field Dog.owner
, must remove this dog from the pet list of previous owner and (if p != null) add itself to the pet list of the new owner. The methods of class Person
to add and remove pets should be visible for the class Dog
but not visible to the user (they should be package private), while the method Dog.setOwner
should be public.
UPDT
We can consider value of Dog.owner
as a primary datum, and value of Person.dogs
as secondary data, similar to database indexes.
Upvotes: 9
Reputation: 3543
What you are required to do looks like a circular dependency issue. So what you can do is to use the object composition.
Simply add to your classes a instance variable of the second type:
public class Person
{
private Dog myDog;
private String name;
private int age;
private String address;
...etc.
and respectively in the Dog
class, every Dog will have its owner:
public class Dog
{
private Person myOwner;
private String name;
private int age;
Don't forget setters and getters.
As for the point 4):
4) Modify your Person class so that a Person object can act as owner for up to 20 Dog objects.
Instead of having every Person
object have one Dog
member, use an array, or some Collection (List, Set, etc.):
So instead of
private Dog myDog;
do
private Dog[] dogArray = new Dog[20];
OR
private Collection<Dog> dogList = new ArrayList(20); //for example
Upvotes: 2
Reputation: 26084
Because both objects can't be created at the same time you can't pass references to each other in the constructor. You must create getter and setter methods so you can create this relationship after the objects are created. An example of this is as follows:
public class Person
Set<Dog> dogs = new HashSet<Dog>();
public void addDog(Dog dog){
if(dogs.size()>20){
throw new IllegalArgumentException("exceeded the limit: ");
}
dogs.add(dog);
}
}
public class Dog
{
Person person;
public void setPerson(Person person){
this.person=person;
}
}
Upvotes: 2
Reputation: 17246
This is a common problem with bidirectional relationships; you can't pass them in the constructor because one will not exist yet when the other is initialised. For this reason you must "wire them up from the outside"
Your mention of 20 dogs suggests they want you to use an array to hold the dogs, but an arraylist would be better. I will use the arraylist but can show you how this would work with an array if you'd like
public class Person
{
ArrayList<Dog> dogs=new ArrayList<Dog>(); //this will hold all the dogs that the Person has as pets
public void giveDog(Dog dog){
dogs.add(dog)
}
.....
.....
Equally the dog class is given an owner
public class Dog
{
Person owner;
public void setOwner(Person owner){
this.owner=owner;
}
.....
.....
Using these two methods you can create the bidirectional relationship.
This is obviously an assignment so you have no choice but for the future; bidirectional relationships like this can be useful. But they are also dangerous when used incorrectly; the most important thing is that after initialisation an object must work without error. It must not rely on setOwner() or giveDog() being called: in other words a petless person and an ownerless dog must behave "correctly" (what ever that means in this context. Failing to achieve this can lead to bug prone code. If this is impracticle then it must be impossible for ownerless dogs or dogless people to be exposed to the rest of the program; factory methods can be useful for this, but that is beyond the scope of this question
Upvotes: 2
Reputation: 3256
Try this one:
Person person = new Person();
Dog dog1 = new Dog();
dog1.setAge(12);
Dog dog2 = new Dog();
dog2.setAge(34);
person.addDog(dog1); //dog 1
person.addDog(dog2); //dog 2
person.listDogs(); //list of all dogs
//PERSON
public class Person {
// instance variables - replace the example below with your own
private String name;
private int age;
private String address;
private ArrayList<Dog> dogs = new ArrayList<Dog>();
/**
* Constructor for objects of class Person
*/
public Person()
{
this.name = name;
this.age = age;
this.address = address;
}
public void addDog(Dog dog) {
this.dogs.add(dog);
}
public void listDogs() {
for(Dog item : this.dogs) {
System.out.println(item.getAge());
}
}
//Set Methods:
public void setName () {
this.name = name;
}
public void setAge () {
this.age = age;
}
public void setAddress () {
this.address = address;
}
//Get Methods:
public String getName () {
return name;
}
public int getAge () {
return age;
}
public String getAddress () {
return address;
}
}
//DOG
public class Dog {
// instance variables - replace the example below with your own
private String name;
private int age;
public Dog()
{
this.name = name;
this.age = age;
}
//Set Methods:
public void setName () {
this.name = name;
}
public void setAge (int age) {
this.age = age;
}
//Get Methods:
public String getName () {
return name;
}
public int getAge () {
return age;
}
}
Upvotes: -2