Видимость рядовых членов С#

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

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

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

Ответы

Ответ 1

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

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

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

Ответ 2

Самый простой способ убедиться, что это программа для интерфейса, например:

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 пытается получить доступ к закрытому полю.

Ответ 3

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

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

Ответ 4

  • Частный просто означает, что к элементу (поле/метод/и т.д.) можно обращаться только от в коде родительского типа. Из CSharpOnline
  • Частные члены нескольких экземпляров видны и могут быть вызваны. Это пригодится, когда вы реализуете "свой конструктор копирования" или "клон" в своем типе, где аргумент является экземпляром того же типа. Если дизайнеры сделают закрытые поля недоступными, вам может понадобиться создать кучу методов getter только для клона/копии, чтобы получить на них. ИМХО, мне нравится, что так оно и есть. В одном и том же типе Чтение другого состояния объекта не так уж плохо, как письмо для него (это может быть соглашение DONT-кода для вас/вашей команды.)

Ответ 5

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

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

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

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

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

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

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

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

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

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

Вышеуказанное затем будет использоваться, написав s1.ExamineStudentsMembers()

Ответ 10

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

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

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

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

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

Ответ 11

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