我对OOP成分有疑问。
让我们说一位母亲有0或更多的孩子,而一个孩子只有一个生物学母亲。
为了说明这一点,我做了以下事情:
public class Mother : ObservableObject
{
// [...]
ObservableCollection<Child> Children {get; set;}
}
public class Child : ObservableObject
{
public Child(Mother mother)
{
this.Mother = mother;
// Adding the child to the mother's children collection
mother.Children.Add(this);
}
public Mother Mother {get; set;}
}
但是我想知道将孩子自动添加到母亲的收藏中是否可以,或者我是否应该使用以下内容:
Mother mother = new Mother();
Child child = new Child(mother);
mother.Children.Add(child);
谢谢:)
答案 0 :(得分:5)
我更喜欢,
public class Mother : ObservableObject
{
// ...
public Child GiveBirth()
{
var newBorn = new Child(this);
this.Children.Add(newBorn);
return newBorn;
}
// ...
}
答案 1 :(得分:2)
我认为建模有点偏差。 Mother
和Child
在语义上彼此相关,但它们是同一对象的实例。它们都是Person
。
创建Person
是由Person
执行的操作。所以Person
甚至不应该有一个公共构造函数,而是一个处理这个逻辑的工厂方法。像这样:
public class Person : ObservableObject
{
private Person()
{
Children = new ObservableCollection<Person>();
}
public Person Mother { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
public Person Procreate()
{
var child = new Person();
child.Mother = this;
this.Children.Add(child);
return child;
}
}
这种建模仍然有点受限,例如我们这里只讨论无性繁殖。所以我们还没有有效地模拟人类。也许我们需要加一个父亲?
public class Person : ObservableObject
{
private Person()
{
Children = new ObservableCollection<Person>();
}
public Person Mother { get; private set; }
public Person Father { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
public Person Procreate(Person father)
{
var child = new Person();
child.Mother = this;
child.Father = father;
this.Children.Add(child);
father.Children.Add(child);
return child;
}
}
我们想要添加一些空值检查,当然还有什么。现在我们还发现我们需要指定性别。 (虽然家庭结构可能差别很大,但创建一个人的行为已经很成熟。)因此我们可以继续添加这样的功能。在某些时候,我们可能确实将这些子类化为子类,但这些子类可能最终成为具有此Person
超类的硬编码默认值的语义传递对象。
但为了好玩,让我们尝试添加性别......
public class Person : ObservableObject
{
private Person(Sex gender, Person mother, Person father)
{
// TODO: Check for null mother and father
this.Gender = gender;
this.Mother = mother;
this.Father = father;
Children = new ObservableCollection<Person>();
}
public Sex Gender { get; private set; }
public Person Mother { get; private set; }
public Person Father { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
public Person Procreate(Person father)
{
// TODO: Check for null father, confirm gender of father
var child = new Person(PickRandomGender(), this, father);
this.Children.Add(child);
father.Children.Add(child);
return child;
}
private Sex PickRandomGender() { /.../ }
public enum Sex
{
Female,
Male
}
}
好的,这很有趣。通过将一些逻辑移动到构造函数来清理一点。但现在还有另一个问题......父亲可以生育。这听起来有点痛苦。现在看来我们已经准备好了子类:
public class Person : ObservableObject
{
protected Person(Sex gender, Person mother, Person father)
{
// TODO: Check for null mother and father
this.Gender = gender;
this.Mother = mother;
this.Father = father;
Children = new ObservableCollection<Person>();
}
public Sex Gender { get; private set; }
public Person Mother { get; private set; }
public Person Father { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
protected Sex PickRandomGender() { /.../ }
public enum Sex
{
Female,
Male
}
}
public class Woman : Person
{
// TODO: Override Gender with a hard-coded value
public Person Procreate(Person father)
{
// TODO: Check for null father, confirm gender of father
var child = new Person(PickRandomGender(), this, father);
this.Children.Add(child);
father.Children.Add(child);
return child;
}
}
(我们是否应该对Man
进行子类化?它在语义上看起来更干净,但是有哪些特定于男性的操作或属性不是女性共享的?也许,但我们的模型还不是那么详细。)
回顾过去,Mother
和Child
的类似乎在这一点上是有限的和短视的。女人不一定是母亲,所有人都是孩子。可以想象,有很多功能可以添加到这个系统中。但是遵循相同的构建域的一般过程应该适应这一点。
答案 2 :(得分:0)
假设您有一个类名构建。这个类的构建具有一个称为BuildRooms()的函数。还有另一个班级的房间,具有创建房间的功能。您将Room类的对象创建为r1,r2,r3等。现在该建筑物有3个房间。我们可以在Room类中打开和关闭门方法。建筑类由房间组成。这意味着该建筑物有3个房间。用您喜欢的任何语言编写代码。这是组成。建筑物中有房间,所以这是Has-A关系。
class building{
void make_rooms()
{
room r1=new room(), r2=new room();
r1.open();
r2.close();
}
}
class room{
void open()
{
}
void close()
{
}
}