0

So I have something like this in my driver class:

Person person1 = new Person(home1, job1);

Home home1 = new Home(person1);

Job job1 = new Job(person1);

where the parameters for the Person constructor are a home and job, and for the home constructor is the owner, and for the job constructor is the employee. How could I make this work?

5
  • It won't, not the way it's currently written. Commented Nov 19, 2013 at 23:22
  • What, specifically, are you trying to accomplish? Commented Nov 19, 2013 at 23:22
  • You can't do that. Your object model is wrong. You shouldn't have classes depending on each other for instantiation. Commented Nov 19, 2013 at 23:23
  • That code needs refactoring. As stated before. There's no way two object can depend on each other for instantiation... it's like the egg or chicken question. Commented Nov 19, 2013 at 23:25
  • Instead, you might for example add an "owner" to a house after construction by using a method like setOwner(Person newOwner) and letting a house have a member variable of the type Person. Commented Nov 19, 2013 at 23:25

5 Answers 5

4

Avoid circular dependencies where possible. However you can do this by wiring them up from the outside. So:

Person person1 = new Person();

Home home1 = new Home(person1);
person1.setHome(home1);

Job job1 = new Job(person1);
person1.setJob(job1);

As I say often unwise, but can be useful on occasion when used carefully. However it is always unwise to do this and make Person rely on .setHome(home1); and .setJob(job1); being called; in otherwords a homeless jobless Person should still operate without error.

Sign up to request clarification or add additional context in comments.

1 Comment

@user2864740 I use it myself with physics engine <--> physics object so I certainly wouldn't write it off. But it can be dangerous when used incorrectly.
3

You can't forward-reference the variable like your code is doing. When creating person1, home1 and job1 haven't been created yet. Because of the interdependency, this approach will always have something being passed to a constructor that isn't itself initialized yet.

You will need to create these objects without the references, then use setter methods after instantiation to create the relationships. Something like this:

Person person1 = new Person();
Home home1 = new Home();
Job job1 = new Job();

person1.setHome(home1);
home1.setOwner(person1);
person1.setJob(job1);
job1.setOnwer(person1);

Comments

3

First of all it's ain't pretty to do something like that, so the best solution will be rethinking solution :)

Anyway, if you really have to do something like that, you can move initialization from constructor to other method (for example setter). One of possible solutions:

public class Home {
     // ...

     public void setPerson(Person person) {
          // ...
     }
}

public class Job {
     // ...

     public void setPerson(Person person) {
          // ...
     }
}

public class Person {

     // ...

     public void Person(Home home, Job job) {
          job.setPerson(this);
          home.setPerson(this);
          // ...
     }
}

// ...
Home home = new Home();
Job job = new Job();
Person person = new Person(home, job);

Comments

2

Assuming Person is your main object (a person has a job and owns a home), you could, in its constructor, create a new Home and a new Job and pass them references to the person.

public class Person {

    private Home home;
    private Job job;

    public Person() {
        this.home = new Home(this);
        this.job = new Job(this);
    }

    public Home getHome() {
        return this.home;
    }

    public Job getJob() {
        return this.job;
    }

}

Your Home and Job classes will obviously have to take a Person in their constructors.

So back in your Driver, all you need is:

Person p = new Person();

Job j = p.getJob();

Home h = p.getHome();

And now you can do whatever you want to with all three.

Comments

2

This is not possible with just constructors - as objects cannot be used before they are created and variables cannot be used before they are assigned (meaningful) values! As such, mutators (or field access) must be used:

// No circular deps yet
Home home1 = new Home();
Job job1 = new Job();
Person person1 = new Person(home1, job1);
// Connect back to person
home1.setPerson(person1);
job1.setPerson(person1);

However, this manual assignment is prone to being forgotten or otherwise incorrectly applied. One way this parent-child relationship establishment can be cleaned up - and is done so in various UI or other Object Graph libraries - is to make the "add" method also establish the opposite relation. Then it can be "simplified" to:

Home home1 = new Home();
Job job1 = new Job();
Person person1 = new Person(home1, job1);
// Note that only one side of the dependency has been manually assigned above!

// Which in turn takes care of the appropriate logic to
// establish the reverse dependency ..
public Person (Home home, Job job) {
   this.home = home;
   this.home.setPerson(this);
   // ..
}

It might also be prudent to add guards such that a Home/Job instance can't be "accidentally" re-assigned to a different person.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.