简体   繁体   English

如何在OO Java中设置两个对象之间的双向关联

[英]How to set up bidirectional association between two objects in OO Java

I have a basic assignment to do but am very new to OOP and struggling with it. 我有一个基本的任务,但对OOP来说是非常新的并且正在努力。 Other online resources are starting to add to my confusion. 其他在线资源开始增加我的困惑。

I am required to: 我需要:

  1. Write code for a class Person. 编写类Person的代码。 A Person object is to have attributes name, age and address. Person对象具有属性名称,年龄和地址。

  2. Write code for a class Dog. 编写类Dog的代码。 A Dog object is to have attributes name and age. Dog对象具有属性名称和年龄。

  3. 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. 在Person和Dog类中提供设置Person对象和Dog对象之间的双向关联所需的任何其他代码。 A Person object acts as an owner for a Dog object and the Dog object acts as a pet for the Person object. Person对象充当Dog对象的所有者,Dog对象充当Person对象的宠物。

  4. Modify your Person class so that a Person object can act as owner for up to 20 Dog objects. 修改Person类,以便Person对象可以充当最多20个Dog对象的所有者。

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. 设置对象之间的关系。

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. 这里的主要问题是一致性:如果Dog d1是Person p1的宠物,那么p1必须是d1的所有者,反之亦然。 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). 如果像许多人建议的那样,我们有2个方法( Person.addDog()Dog.setOwner() ),那么用户很容易犯错并且无法调用这两个方法(或者使用错误的参数调用)。 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. 由于Dog只能拥有一个所有者,因此简单而安全的界面将使用单一方法Dog.setOwner(Person p) ,如果我们希望狗没有所有者,则p可以为null。 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. 除了设置字段Dog.owner之外,此方法必须从前一个所有者的宠物列表中删除此狗,并且(如果p!= null)将其自身添加到新所有者的宠物列表中。 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. 类的方法Person添加和删除宠物应该是类可见Dog ,但对用户不可见的(他们应该是包专用),而该方法Dog.setOwner应该是公开的。

UPDT We can consider value of Dog.owner as a primary datum, and value of Person.dogs as secondary data, similar to database indexes. UPDT我们可以将Dog.owner值视为主要数据,并将Person.dogs值视为辅助数据,类似于数据库索引。

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. 你提到的20只狗表明他们希望你用一个阵列来抓住狗,但是一个arraylist会更好。 I will use the arraylist but can show you how this would work with an array if you'd like 我将使用arraylist,但如果您愿意,可以告诉您如何使用数组

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. 使用这两种方法可以创建双向关系。

Notes 笔记

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 它不能依赖于调用setOwner()或giveDog():换句话说,一个无家伙的人和一个无主的狗必须表现得“正确”(在这种情况下这意味着什么。未能实现这一点可能会导致容易出错的代码。如果这是不切实际的话,那么无主的狗或无狗的人就不可能接触到其他程序;工厂方法对此有用,但这超出了这个问题的范围

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: 并且在Dog类中,每只狗都会拥有它的主人:

public class Dog
{
    private Person myOwner;

    private String name;
    private int age;

Don't forget setters and getters. 不要忘记制定者和吸气者。

As for the point 4): 至于第4点):

4) Modify your Person class so that a Person object can act as owner for up to 20 Dog objects. 4)修改Person类,以便Person对象可以充当最多20个Dog对象的所有者。

Instead of having every Person object have one Dog member, use an array, or some Collection (List, Set, etc.): 而不是让每个Person对象都有一个Dog成员,使用数组或一些Collection(List,Set等):

So instead of 而不是

private Dog myDog;

do

private Dog[] dogArray = new Dog[20];
OR
private Collection<Dog> dogList = new ArrayList(20); //for example

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. 您必须创建getter和setter方法,以便在创建对象后创建此关系。 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;
    }
}

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;
    }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM