如何在OO Java中设置两个对象之间的双向关联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20097945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set up bidirectional association between two objects in OO Java
提问by Anon Omus
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.
我有一个基本的任务要做,但我对 OOP 很陌生并且正在为此苦苦挣扎。其他在线资源开始增加我的困惑。
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.
为类 Person 编写代码。Person 对象具有名称、年龄和地址属性。
为 Dog 类编写代码。Dog 对象具有属性名称和年龄。
在 Person 和 Dog 类中提供在 Person 对象和 Dog 对象之间设置双向关联所需的任何附加代码。Person 对象充当 Dog 对象的所有者,而 Dog 对象充当 Person 对象的宠物。
修改您的 Person 类,以便一个 Person 对象可以充当最多 20 个 Dog 对象的所有者。
Obviously this is a very simple example.
显然这是一个非常简单的例子。
My codeso 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.
这就是我的问题所在。设置对象之间的关系。
回答by Richard Tingle
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
您提到 20 只狗表明他们希望您使用数组来保存狗,但数组列表会更好。我将使用 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() 被调用:换句话说,一个没有宠物的人和一个没有主人的狗必须表现得“正确”(在这种情况下这意味着什么。未能实现这一点可能会导致代码容易出错。如果这是不切实际的,那么没有主人的狗或没有狗的人肯定不可能暴露于程序的其余部分;工厂方法对此很有用,但这超出了本问题的范围
回答by Eel Lee
What you are required to do looks like a circular dependencyissue. 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.
不要忘记 setter 和 getter。
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
成员,而是使用数组或一些集合(列表、集合等):
So instead of
所以代替
private Dog myDog;
do
做
private Dog[] dogArray = new Dog[20];
OR
private Collection<Dog> dogList = new ArrayList(20); //for example
回答by Dezigo
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;
}
}
回答by Prabhakaran Ramaswamy
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:
因为不能同时创建两个对象,所以不能在构造函数中相互传递引用。您必须创建 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;
}
}
回答by Alexei Kaigorodov
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.
这里的主要问题是一致性:如果狗 d1 是人 p1 的宠物,那么 p1 必须是 d1 的所有者,反之亦然。如果正如许多人所建议的那样,我们有 2 个方法(Person.addDog()
和Dog.setOwner()
),那么用户很容易犯错误并且无法调用这两个方法(或使用错误的参数调用)。由于一只狗只能有一个主人,一个简单而安全的接口将使用单一方法Dog.setOwner(Person p)
,p
如果我们希望狗没有主人,则可以为 null。此方法除了设置 field 外Dog.owner
,还必须将这条狗从前主人的宠物列表中删除,并且(如果 p != null)将自己添加到新主人的宠物列表中。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
当作次要数据,类似于数据库索引。