【问题标题】:How to get access to an object which is in a different class while maintaining encapsulation? (data?)如何在保持封装的同时访问不同类中的对象? (数据?)
【发布时间】:2019-11-06 11:55:57
【问题描述】:

我正在用 c# 制作一个电话簿控制台应用程序,这是我迄今为止最大的项目 :) 我认为自己是初学者,但我很想改进

我使用 3 个类来创建它,它们是:

  • 修改
  • 搜索
  • 显示

Modifications 类负责添加、删除和编辑联系人。 Search 和 Display 类是不言自明的。我也有这些类的接口。


问题:

我在 Modifications 类中创建了一个 KeyValuePair 列表,如下所示:

private List<KeyValuePair<string , int>> AllContacts { get; set; } 

public Modifications()
{ 
   AllContacts = new List<KeyValuePair<string, int>>(); 
}

我想在我的其他课程中访问这个AllContacts 对象。但是我在保持封装的同时未能实现这一点。 AllContacts 就像我的主要数据来源。我在此列表中添加联系人。我不希望我的主要方法中的某个人像modificationObject.AllContacts.Clear();


我的尝试:

[如果你愿意,可以跳过这个:)]

我的悲伤尝试第 1 部分:

-从基类修改继承显示类

-在我的 Modifications 类中,我创建了一个 List&lt;KeyValuePair&lt;string , int&gt;&gt; 类型的受保护属性并将其命名为“AllContacts”作为数据库

-在我的 Display 类中,我创建了一个与上面相同类型的私有属性并将其命名为 _allContacts

-在我的 Display 类的构造函数中,我请求了一个名为 modObject 的修改类型对象

-我说,_data = modObject.AllContacts;

-没用,我猜是因为只有派生对象才能获得这个属性?

我的悲伤尝试第 2 部分:

-假设我的假设是正确的,我尝试将 modObject 向下转换为它的派生类类型 Display。反而得到编译错误。试图创建一个受保护的GetAllContacts() 方法,编译错误。

我的悲伤尝试第 6 部分:

-最后,我只是将其设置为带有私有设置器的公共属性。我的应用程序有效,但人们仍然可以以某种方式在我的 main 方法中使用x.AllContacts.Clear()


问题:

  • 如何在不破坏封装的情况下在其他类中使用AllContactsobject?有没有可能?

  • 最初,我为数据创建了一个单独的类,并且我还有 3 个其他类(修改、搜索和显示),这是一个更好的设计,对吧?我在其他类中访问该数据对象时遇到了同样的问题。

谢谢:)


如果需要,附加上下文:(当前工作的应用程序,没有方法)

修改类:

 public class Modifications
    {
        public List<KeyValuePair<string, int>> AllContacts { get; private set; }
        public Modifications()
        {
            AllContacts = new List<KeyValuePair<string, int>>();
        }
....

显示类:

public class Display : IDisplayable
{
    private List<KeyValuePair<string, int>> AllContacts;
    public Display(Modifications modificationsObject)
    {
        AllContacts = modificationsObject.AllContacts;
    }

....


【问题讨论】:

  • 您好,欢迎!你对封装的理解是正确的。 AllContacts 将保持私有状态,只需为其他类添加 setter 和 getter 方法即可对其进行访问。如果 Search 和 DISplay 只读取这个列表,只暴露一个 getter 方法,这不会违反封装规则
  • 要么公开 AllContacts 列表,要么添加设置和返回 AllContacts 对象的 getter 和 setter :)
  • 搜索和显示类有什么作用?如果它们与相同的内容相关,为什么它们不在同一个类中?
  • 您过度设计了东西,使课程太小,添加了太多课程等。您基本上是在要求您需要将私有财产作为公共财产。那为什么要把它定义为私有财产呢?把这一切都放在一个班级里,这将是最好的选择。
  • @Djuro 是的,看起来是这样,我所有的课程都与电话簿有关,但我正在分离迷你功能,比如它们是否修改数据,或者它们是否只显示数据或是否正在搜索。我应该把所有东西都放在电话簿类中,对吧?

标签: c# oop encapsulation


【解决方案1】:

您不需要为私有变量成员声明访问器,除非您想禁止所有其他方法的 setter,但是使用 readonly 字段比使用属性更优化速度,从而避免消耗滴答计时的无用 CPU Proc 调用什么都没有。

要从其他类访问它,您必须像这样将其声明为公共:

public List<KeyValuePair<string , int>> AllContacts { get; private set; } 

因此其他类可以读取引用并调用 List 实例的变量访问器和方法,例如 Count 和 Add,但它们不能替换此实例引用,从而更改对象本身。

但是如果你想禁止对列表的操作,你可以实现所有你想公开的包装方法,如 Count、Add、Delete、Remove 等以及索引器,你可以指出该类实现了IExumerable&lt;KeyValuePair&lt;string , int&gt;&gt; .

通过这种方式可以进行强封装:

public class MyClass: IEnumerable<KeyValuePair<string , int>>
{
  private readonly List<KeyValuePair<string , int>> AllContacts
    = new List<KeyValuePair<string , int>>();

  public int ContactsCount
  {
    get { return AllContacts.Count; }
  }

  public KeyValuePair<string , int> this[int index]
  {
    get { return AllContacts[index]; }
    set { AllContacts[index] = value; }  // don't declare if readonly
  }

  // if adding is allowed
  public int Add(KeyValuePair<string , int> item)
  {
    ...
  }

  ...

}

【讨论】:

  • 隐式它仍在暴露访问器
  • 您好,您的回答非常通俗易懂!我知道您实际上只是在赠送对象的零碎!虽然我得出的结论是我不必要地创建了太多类,你同意吗?
  • 我真的不明白你打算用类做什么,但这是一个意见和设计模式的问题。您可以在一个类中执行操作,也可以创建多个处理类来操作一个数据类。这首先取决于您的高级设计、复杂性以及用例。这取决于如何访问和处理封装的数据,通过什么、何时、如何等。因此,根据所需的二分法/隔离和作用的实体,拥有一个数据类和一些类来创建数据、显示数据、修改数据等会很好。
猜你喜欢
  • 2018-03-02
  • 1970-01-01
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
  • 1970-01-01
  • 2019-08-28
  • 1970-01-01
相关资源
最近更新 更多