Как получить доступ к объекту другого класса при сохранении инкапсуляции? (данные?) - PullRequest
0 голосов
/ 06 ноября 2019

Я делаю консольное приложение для телефонной книги на c #, и это мой самый большой проект на данный момент :) Я считаю себя новичком, но я бы хотел улучшить

Я использую 3 класса для создания этого,вот они:

  • Модификации
  • Поиск
  • Отображение

Модификации класса отвечает за добавление, удаление и редактирование контактов. Классы поиска и отображения говорят сами за себя. У меня также есть интерфейсы для каждого из этих классов.


Проблема:

Я создал список KeyValuePair внутри класса Модификации, например:

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

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

Я хотел бы получить доступ к этому AllContacts объекту вмои другие занятия. Но мне не удалось этого достичь при сохранении инкапсуляции. AllContacts похоже на мой основной источник данных. Я добавляю контакты в этот список. Я не хочу, чтобы кто-то в моем основном методе походил на modificationObject.AllContacts.Clear();


Мои попытки:

[пропустите это, если хотите :)]

Моя грустная попытка, часть 1:

- Унаследованный класс отображения из базового класса Модификации

- в моем классе Модификаций я создал защищенное свойство типаList<KeyValuePair<string , int>> и назвал его 'AllContacts' в качестве базы данных

- в моем классе Display я создал частное свойство того же типа, что и выше, и назвал его _allContacts

- в конструкторе моего дисплеякласс, я запросил объект типа Модификация с именем его modObject

-Я заявил, _data = modObject.AllContacts;

-Это не сработало, я полагаю, это потому, что только производные объекты могут получить это свойство?

Моя грустная попытка, часть 2:

- Предполагая, что мое предположение верно, я попытался понизить modObject до его производного типа класса, Display,Получил ошибку компиляции. Пытался сделать защищенный GetAllContacts() метод, ошибка компиляции.

Моя грустная попытка Часть 6:

-В конце я только что сделалэто публичная собственность с частным сеттером. Мое приложение работает, но люди все равно могут использовать x.AllContacts.Clear() в моем основном методе.


Вопросы:

  • Как я могу использовать AllContacts объект вдругие классы без нарушения инкапсуляции? Это вообще возможно?

  • Изначально я создал отдельный класс для данных, и у меня было 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;
    }

....


1 Ответ

1 голос
/ 06 ноября 2019

Вам не нужно объявлять методы доступа для элемента с частной переменной, если вы не хотите запретить установщик для всех других методов, но скорость использования оптимизирована для использования поля только для чтения, чем свойство, позволяющее избежать бесполезных обращений к процессору ЦП, которые потребляют время тиков дляНичего.

Чтобы получить доступ к нему из других классов, вы должны объявить его как открытый так:

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

Чтобы другие классы могли читать ссылку и вызывать методы доступа к переменным и методы экземпляра List, напримерCount и Add, но они не могут заменить эту ссылку на экземпляр и, таким образом, изменить сам объект.

Но если вы хотите запретить манипулирование списком, вы можете реализовать все упакованные методы, которые вы хотите выставить, такие как Count, Add, Delete, Remove и так далее, а также индексатор, и вы можете указать, что класс реализует IExumerable<KeyValuePair<string , int>>.

. Таким образом, вы можете иметь сильную инкапсуляцию:

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)
  {
    ...
  }

  ...

}
...