例如,每个人可以有多个孩子,但每个人必须有两个父母。那么说(在C#中)
是否合理class Human {}
class Father : Human
{
List<Child> Children {get; set;}
}
class Mother : Human
{
List<Child> Children {get; set;}
}
class Child : Human
{
Mother Mother {get; set;}
Father Father {get; set;}
}
(另一个例子是一本书的页面 - 一本书可以有多个页面但是一个页面必须属于一本且只有一本书,假设我们没有介绍书籍撕裂页面的概念,添加页面等)< / p>
我知道在OOP中,子对象中的父引用会破坏封装并增加耦合。但是,如果子对象没有父对象没有意义,那么向子对象添加父引用是否正确?
答案 0 :(得分:1)
我知道在OOP中,子对象中的父引用会破坏封装......
不,它没有。如果来自外部的代码应该有理由关心存在这种关系,那么允许来自外部的代码知道。代码不需要知道该关系是否由引用实现,事实上它并非必须如此。揭示这将破坏封装。
......并增加耦合。
啊,确实如此。
所以你需要:
如果您的课程不可变,那么您应该感到高兴的一种简单方法就是:当您收到Human
Mother
,Father
和/或Children
时{1}}属性是固定的,只读,然后耦合也是固定的,不会伤害你。 (如果你有一个引用计数的垃圾收集,但这可能是.NET,所以你不要)。这不是你可能不关心的唯一方式,但它是一个。
否则你需要处理那个耦合。一种方法是只从外部设置Mother
和Father
属性。考虑:
public class Human
{
private Human _mother;
private Human _father;
private HashSet<Human> _children;
public IEnumerable<Human> Children
{
// If paranoid, do a foreach … yield here to stop code casting back to `HashSet`
// Using ImmutableCollections and calling ToImmutableHashSet() is good too.
get { return _children; }
}
public Human Mother
{
get { return _mother; }
set
{
if(_mother == value) // skip for no-op
return;
if(_mother != null)
_mother._children.Remove(this);
if(value != null)
value._children.Add(this);
_mother = value;
}
}
public Human Father
{
get { return _father; }
set
{
if(_father == value)
return;
if(_father != null)
_father._children.Remove(this);
if(value != null)
value._children.Add(this);
_father = value;
}
}
}
此方法通过在Father
和Mother
属性中处理耦合来处理耦合,并且仅在这些属性中处理。其他方法适用于其他情况,例如,根本不存储这些属性的值,但在调用属性时可以获取它们。
当然也可以让所有Mother
,Father
和Children
属性都可写(以及通过访问Children
可写的集合也是可以的)`并且仍然保持同步,它很难。它是否比它必须更难取决于应用程序。
而不是打破封装,他们非常依赖它。