如果孩子在没有父母的情况下不能存在,那么孩子的父母参考是否合理?

时间:2015-05-30 12:40:36

标签: c# oop

例如,每个人可以有多个孩子,但每个人必须有两个父母。那么说(在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中,子对象中的父引用会破坏封装并增加耦合。但是,如果子对象没有父对象没有意义,那么向子对象添加父引用是否正确?

1 个答案:

答案 0 :(得分:1)

  

我知道在OOP中,子对象中的父引用会破坏封装......

不,它没有。如果来自外部的代码应该有理由关心存在这种关系,那么允许来自外部的代码知道。代码不需要知道该关系是否由引用实现,事实上它并非必须如此。揭示这将破坏封装。

  

......并增加耦合。

啊,确实如此。

所以你需要:

  1. 很高兴您不关心这一点。
  2. 在明确定义的地方处理耦合。
  3. 如果您的课程不可变,那么您应该感到高兴的一种简单方法就是:当您收到Human MotherFather和/或Children时{1}}属性是固定的,只读,然后耦合也是固定的,不会伤害你。 (如果你有一个引用计数的垃圾收集,但这可能是.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属性中处理耦合来处理耦合,并且仅在这些属性中处理。其他方法适用于其他情况,例如,根本不存储这些属性的值,但在调用属性时可以获取它们。

    当然也可以让所有MotherFatherChildren属性都可写(以及通过访问Children可写的集合也是可以的)`并且仍然保持同步,它很难。它是否比它必须更难取决于应用程序。

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