【问题标题】:How to set up bidirectional association between two objects in OO Java如何在 OO Java 中建立两个对象之间的双向关联
【发布时间】:2013-12-04 13:32:07
【问题描述】:

我有一项基本任务要做,但我对 OOP 非常陌生,并且正在为此苦苦挣扎。其他在线资源开始增加我的困惑。

我必须:

  1. 为 Person 类编写代码。 Person 对象具有名称、年龄和地址属性。

  2. 为 Dog 类编写代码。 Dog 对象将具有属性名称和年龄。

  3. 在 Person 和 Dog 类中提供在 Person 对象和 Dog 对象之间建立双向关联所需的任何附加代码。 Person 对象充当 Dog 对象的所有者,而 Dog 对象充当 Person 对象的宠物。

  4. 修改您的 Person 类,以便一个 Person 对象可以充当最多 20 个 Dog 对象的所有者。

显然这是一个非常简单的例子。

到目前为止我的代码

人物类:

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

狗类:

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


}

主要:

public class Main
{
   //Blank 
}

我知道这段代码目前没有用,也没有做任何事情,但我不确定如何“关联”对象以及在哪里做。分配规范指定一个人充当狗的“所有者”。

这就是我的问题所在。设置对象之间的关系。

【问题讨论】:

  • 您希望关系是内部的(比如一个人有一组 Dogs 作为字段,而狗有一个所有者作为字段)还是外部的(例如包含关系的地图)
  • 我认为内部规范指定我必须这样做
  • "修改 Person 类,使 Person 对象可以作为最多 20 个 Dog 对象的所有者。"
  • 只需在 Person 中添加 setDog(Dog pet) 方法,然后在 Dog 中添加 setOwner(Person owner) 方法。就这么简单:)
  • 好莱坞原则 ;)

标签: java class oop object


【解决方案1】:

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

UPDT 我们可以将Dog.owner的值作为主要数据,将Person.dogs的值作为辅助数据,类似于数据库索引。

【讨论】:

    【解决方案2】:

    这是双向关系的常见问题;您不能在构造函数中传递它们,因为当另一个初始化时,其中一个将不存在。因此,您必须“从外部将它们连接起来”

    您提到 20 只狗表明他们希望您使用数组来容纳狗,但数组列表会更好。我将使用数组列表,但如果你愿意,我可以向你展示它如何与数组一起工作

    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)
        }
        .....
        .....
    

    同样地,狗类也有一个主人

    public class Dog
        {
        Person owner;
    
        public void setOwner(Person owner){
           this.owner=owner;
        }
        .....
        .....
    

    使用这两种方法可以创建双向关系。

    注意事项

    这显然是一项任务,所以你别无选择,只能为未来;像这样的双向关系可能很有用。但是如果使用不当,它们也很危险;最重要的是,在初始化之后,对象必须正常工作。它不能依赖于 setOwner() 或 giveDog() 被调用:换句话说,没有宠物的人和没有主人的狗必须表现得“正确”(在这种情况下这意味着什么。未能实现这一点可能会导致代码容易出错。如果这是不切实际的,那么没有主人的狗或没有狗的人一定不可能接触到程序的其余部分;工厂方法对此可能有用,但这超出了这个问题的范围

    【讨论】:

      【解决方案3】:

      因为不能同时创建两个对象,所以不能在构造函数中相互传递引用。您必须创建 getter 和 setter 方法,以便在创建对象后创建这种关系。一个例子如下:

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

      【讨论】:

      • 我不是“这里:代码!”的忠实粉丝。答案。一些解释会很有帮助,否则 OP 所能做的就是复制、粘贴和希望
      • 我添加了一小段来解释发生了什么,希望对您有所帮助
      【解决方案4】:

      您需要做的事情看起来像是circular dependency 问题。所以你可以做的是使用object composition

      只需将第二种类型的实例变量添加到您的类中:

      public class Person
      {
          private Dog myDog;
      
          private String name;
          private int age;
          private String address;
          ...etc.
      

      并且分别在Dog 类中,每只狗都会有它的主人:

      public class Dog
      {
          private Person myOwner;
      
          private String name;
          private int age;
      

      不要忘记 setter 和 getter。

      至于第4点):

      4) 修改您的 Person 类,以便 Person 对象可以充当最多 20 个 Dog 对象的所有者。

      不要让每个Person 对象都有一个Dog 成员,而是使用一个数组或某个集合(List、Set 等):

      所以不是

      private Dog myDog;
      

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

      【讨论】:

        【解决方案5】:

        试试这个:

            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
        

        //人

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

        //狗

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

        【讨论】:

        • 我假设的原因与其他被否决的答案相同。 “这里:代码!”除非它是一个班轮,否则答案并不能真正帮助任何人。一些解释会很有帮助,否则 OP 所能做的就是复制、粘贴和希望
        • stackoverflow.com/help/privileges/vote-down 我什么时候应该投反对票?每当您遇到极其草率、不费吹灰之力的帖子或明显不正确且可能危险地不正确的答案时,请使用您的反对票。
        猜你喜欢
        • 2023-03-30
        • 2013-04-22
        • 2011-10-10
        • 1970-01-01
        • 2019-10-18
        • 2018-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多