如果子元素没有父元素就不能存在,那么子元素中的父引用是否合理?

本文关键字:元素 引用 是否 就不能 存在 如果 | 更新日期: 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中,子对象中的父引用会破坏封装…

不,它没有。如果来自外部的代码应该有理由关心存在这样的关系,那么来自外部的代码应该被允许知道。代码不需要知道该关系是否由引用实现,实际上也不必知道。

…并增加耦合。

啊,好吧。

所以你需要:

  1. 很高兴你不关心这个。
  2. 在定义良好的地方处理耦合。

如果你的类是不可变的,你会很高兴,如果你的类是不可变的:当你收到一个Human,它的Mother, Father和/或Children属性是固定的和只读的,那么耦合也是固定的,不会伤害你。(如果你有一个引用计数的垃圾收集,可能会这样,但这是。net,所以你没有)。这不是你可能不关心的唯一方式,但它是一种。

否则,您需要处理这种耦合。一种方法是从外部只设置MotherFather属性。考虑:

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

这种方法通过在FatherMother属性中处理耦合,并且只在这些属性中处理耦合。其他方法适用于其他情况,例如根本不存储这些属性的值,但在调用属性时可以获得这些值。

当然也有可能让所有的Mother, FatherChildren属性都是可写的(通过访问Children获得的集合也是可写的),并且仍然保持同步,这很难。是否比实际情况更困难取决于应用程序。

它们不是打破封装,而是非常依赖于它。