如果子元素没有父元素就不能存在,那么子元素中的父引用是否合理?
本文关键字:元素 引用 是否 就不能 存在 如果 | 更新日期: 2023-09-27 17:51:15
例如,每个人可以有多个孩子,但每个人必须有两个父母。那么(在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;}
}
(另一个例子是一本书的页——一本书可以有多页,但一页必须属于且只能属于一本书,假设我们不引入撕页、加页等概念)
我知道在OOP中,子对象中的父引用破坏了封装并增加了耦合。但是,如果子对象没有父对象是没有意义的,那么向子对象添加父引用是正确的吗?
我知道在OOP中,子对象中的父引用会破坏封装…
不,它没有。如果来自外部的代码应该有理由关心存在这样的关系,那么来自外部的代码应该被允许知道。代码不需要知道该关系是否由引用实现,实际上也不必知道。
…并增加耦合。
啊,好吧。
所以你需要:
- 很高兴你不关心这个。
- 在定义良好的地方处理耦合。
如果你的类是不可变的,你会很高兴,如果你的类是不可变的:当你收到一个Human
,它的Mother
, Father
和/或Children
属性是固定的和只读的,那么耦合也是固定的,不会伤害你。(如果你有一个引用计数的垃圾收集,可能会这样,但这是。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
获得的集合也是可写的),并且仍然保持同步,这很难。是否比实际情况更困难取决于应用程序。
它们不是打破封装,而是非常依赖于它。