Ответ 1
Есть простой способ обеспечить это:
Не вмешивайтесь в личные члены других экземпляров одного и того же класса.
Серьезно - вы пишете код Student
.
У нас есть класс 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);
}
}
Могу ли я поразмыслить над соображениями дизайна/последствиями этого. Кажется, что вы не можете скрывать информацию от своих братьев и сестер. Есть ли способ пометить поле или элемент как скрытые от других экземпляров одного и того же класса?
Есть простой способ обеспечить это:
Не вмешивайтесь в личные члены других экземпляров одного и того же класса.
Серьезно - вы пишете код Student
.
Самый простой способ убедиться, что это программа для интерфейса, например:
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 пытается получить доступ к закрытому полю.
Если вы пишете класс, у вас есть полный контроль над ним, поэтому, если вы не хотите, чтобы один объект мог изменять другой, не пишите в эту функциональность.
Классы часто используют частные переменные в других экземплярах для реализации эффективных функций сравнения и копирования.
Доступ к частным данным sibling может показаться неправильным, если он сформулирован следующим образом:
public void ExamineStudentsMembers(Student anotherStudent) {
//this seems very wrong
Console.WriteLine(anotherStudent._studentsPrivateMember);
}
Тем не менее, это не кажется таким странным для методов, которые требуют такой функции. Какие методы требуют доступа к конфиденциальным данным sibling? Методы сравнения (в частности, равны) и объекты в структуре данных (например, дерево или связанный список).
Методы сравнения часто сравнивают частные данные напрямую, а не только общедоступные данные.
Для класса узлов, которые составляют связанный список, граф или дерево, возможность доступа к отдельным данным личного состава является именно тем, что необходимо. Код в курсе (часть класса) может возиться со структурой данных, но код за пределами структуры данных не может касаться внутренних элементов.
Интересно отметить, что эти два случая менее распространены в повседневном программировании, чем когда эта языковая функция была впервые разработана. Еще в 1990-х и начале 2000-х годов на С++ было бы гораздо более распространено создание пользовательских структур данных и методов сравнения. Возможно, самое время пересмотреть частные члены.
Мне нравится вторая точка, вы можете посмотреть, но не прикасайтесь к тем частным членам.
Забавно, что вы должны сказать, что однажды я знал учителя, и он сказал, что у него часто возникала проблема, решающая, на каких классах было нормально смотреть на членов и на какие из них он мог бы играть.
Объект - это всего лишь часть данных; класс содержит функциональность. Метод участника - это просто хороший трюк, который играет компилятор; это больше похоже на статический метод с подразумеваемым аргументом (вроде методов расширения). Имея это в виду, защита объектов друг от друга не имеет никакого смысла; вы можете защищать только классы друг от друга. Поэтому естественно, что он работает именно так.
Нет, это необходимо, код метода не специфичен для экземпляра, он специфичен только для типа объекта. (виртуальные методы) или объявленный тип переменной (для не виртуальных методов). С другой стороны, нестатические поля специфичны для экземпляра... То, что у вас есть изоляция на уровне экземпляра.
Единственное отличие статического метода от нестатического метода заключается в том, что статическому методу не разрешается обращаться к другим методам или полям, основанным на экземплярах. Любой метод, который может быть сделан статическим без изменений, никоим образом не будет затронут, сделав его статическим, за исключением того, чтобы заставить компилятор выбросить ошибки в любом месте, где он был вызван с использованием синтаксиса на основе экземпляра.
Если вы намерены изучить данные учащегося, я бы изменил метод на статический:
public static void ExamineStudentsMembers(Student student)
{
Console.WriteLine(student._studentsPrivateMember);
}
Затем вы использовали бы Student.ExamineStudentsMembers(s1)
. Использование s1.ExamineStudentsMembers(s2)
будет недействительным.
Если это не намеренная цель, я бы переписал метод как:
public void ExamineStudentsMembers()
{
Console.WriteLine(_studentsPrivateMember);
}
Вышеуказанное затем будет использоваться, написав s1.ExamineStudentsMembers()
Частные члены должны скрывать детали реализации от клиентов. Клиенты должны видеть только интерфейс (общедоступные методы/поля/свойства).
Цель состоит не в том, чтобы защитить программиста от себя.
Это также НЕ функция безопасности, потому что вы всегда можете получить доступ к закрытым полям через отражение.
Это действительно отдельный интерфейс и реализация (дизайн черного ящика), а клиенты программируют против контракта (все публичные поля).
Например, если у вас есть свойство public get, оно может напрямую обращаться к частному полю или может вычислять значение из других полей. Цель заключается в том, что клиент знает контракт (публичное свойство), и реализация может быть изменена без ущерба для клиента
Объектная область не никогда не подразумевает безопасность - никогда! Это роль ОС для обеспечения безопасности во время выполнения. Это ошибка для разработки системы, которая опирается на область конкретных объектов на языке, чтобы ограничить доступ к данным экземпляра объекта времени исполнения. Если это не так, то все неязыковые языки по определению не защищены.