C # Видимость частных членов - PullRequest
13 голосов
/ 19 января 2010

У нас есть студенческий класс в нашей бизнес-модели. что-то показалось мне странным, если мы манипулируем одним учеником другого ученика, его личные члены видны ... это выглядит немного неприлично

   class Program {
      static void Main(string[] args) {

         Student s1 = new Student();
         Student s2 = new Student();

         s1.ExamineStudentsMembers(s2);
      }
   }

   public class Student {

      private String _studentsPrivateMember;

      public Student() {
         _studentsPrivateMember = DateTime.Now.Ticks.ToString();
      }

      public void ExamineStudentsMembers(Student anotherStudent) {
         //this seems very wrong
         Console.WriteLine(anotherStudent._studentsPrivateMember);
      }
   }

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

Ответы [ 11 ]

9 голосов
/ 19 января 2010

Есть простой способ обеспечить это:

Не связывайтесь с закрытыми членами других экземпляров того же класса.

Серьезно - вы тот, кто пишет код Student.

8 голосов
/ 19 января 2010

Самый простой способ убедиться в этом - запрограммировать интерфейс, такой как:

class Program
{
    static void Main(string[] args)
    {
        IStudent s1 = new Student();
        IStudent s2 = new Student();

        s1.ExamineStudentsMembers(s1);
    }
}

public interface IStudent
{
    void ExamineStudentsMembers(IStudent anotherStudent);
}

public class Student : IStudent
{
    private string _studentsPrivateMember;

    public Student()
    {
        _studentsPrivateMember = DateTime.Now.Ticks.ToString();
    }

    public void ExamineStudentsMembers(IStudent anotherStudent)
    {
        Console.WriteLine(anotherStudent._studentsPrivateMember);
    }
}

Это больше не будет компилироваться из-за того, что ExamineStudentsMembers пытается получить доступ к приватному полю.

5 голосов
/ 19 января 2010

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

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

4 голосов
/ 19 января 2010
  • Приватный просто означает, что к члену (полю / методу / и т. Д.) Можно получить доступ только из в коде родительского типа CSharpOnline
  • Закрытые члены нескольких экземпляров видны и могут быть вызваны.Это удобно, когда вы реализуете «конструктор копирования» или метод «клон» для вашего типа, где аргумент является экземпляром того же типа.Если бы дизайнеры сделали закрытые поля недоступными, вам, возможно, придется создать набор методов получения только для того, чтобы клонировать / копировать, чтобы получить к ним доступ.ИМХО, мне больше нравится так, как есть.Внутри того же типа чтение состояния другого объекта не так уж и плохо, как запись в него (что может быть DONT-кодом для вас / вашей команды).
2 голосов
/ 19 января 2010

мне нравится второй пункт, вы можете посмотреть, но не трогайте этих частных членов.

Забавно, ты должен сказать, что я однажды знал учителя, и он сказал, что ему часто бывает трудно решить, с какими классами нормально смотреть на участников, а с какими он мог бы поиграть.

2 голосов
/ 19 января 2010

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

public void ExamineStudentsMembers(Student anotherStudent) {
    //this seems very wrong
    Console.WriteLine(anotherStudent._studentsPrivateMember);
}

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

Методы сравнения часто сравнивают личные данные напрямую, а не только публичные данные.

Для класса узлов, которые составляют связанный список, граф или дерево, возможность доступа к личным данным родного брата - это именно то, что нужно. Известный код (часть класса) может возиться со структурой данных, но код вне структуры данных не может касаться внутренних элементов.

Интересно отметить, что эти два случая менее распространены в повседневном программировании, чем когда впервые была разработана эта языковая функция. Еще в 1990-х и начале 2000-х годов в C ++ было бы гораздо чаще создавать собственные структуры данных и методы сравнения. Возможно, сейчас самое время пересмотреть вопрос о частных членах.

1 голос
/ 19 января 2010

Объект - это просто часть данных; класс содержит функциональность. Метод member - это просто хороший трюк, который играет компилятор; это действительно больше похоже на статический метод с подразумеваемым аргументом (вроде как методы расширения) Имея это в виду, защита объектов друг от друга не имеет никакого смысла; вы можете только защитить классы друг от друга. Поэтому вполне естественно, что так и происходит.

0 голосов
/ 27 июня 2017

Частные участники должны скрывать детали реализации от клиентов.Клиенты должны видеть только интерфейс (публичные методы / поля / свойства).

Цель не в том, чтобы защитить программиста от самого себя.

Это также НЕ функция безопасности, потому что вы всегда можетедоступ к закрытым полям с помощью отражения.

Это действительно для разделения интерфейса и реализации (дизайн черного ящика) и клиентов, программирующих на основе контракта (все открытые поля).

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

0 голосов
/ 19 января 2010

Объем объекта не никогда не подразумевает безопасность - никогда! Это роль ОС для обеспечения безопасности во время выполнения. Это ошибка в разработке системы, которая использует язык объекта для ограничения доступа к данным экземпляра объекта во время выполнения. Если это не так, то все языки, не относящиеся к ОО, по определению не являются безопасными.

0 голосов
/ 19 января 2010

Если вы намереваетесь изучить информацию данного учащегося, я бы изменил метод на статический:

  public static void ExamineStudentsMembers(Student student)
  {
     Console.WriteLine(student._studentsPrivateMember);
  }

Вы бы тогда использовали Student.ExamineStudentsMembers(s1). Использование s1.ExamineStudentsMembers(s2) будет недопустимым.

Если это не цель, я бы переписал метод следующим образом:

  public void ExamineStudentsMembers()
  {
     Console.WriteLine(_studentsPrivateMember);
  }

Приведенное выше будет использовано при написании s1.ExamineStudentsMembers()

...