Подтвердить что ты не робот

Назначение частных членов в классе

Каковы цели наличия частных/защищенных членов класса/структуры в объектно-ориентированном программировании? Какой вред в том, что все участники будут публичными?

4b9b3361

Ответ 1

Герметизация. То есть скрывая реализацию данных вашего класса. Это позволяет вам впоследствии изменить его, не нарушая всех клиентских кодов. Например. если у вас есть

class MyClass {
    public int foo;
}

ваши клиенты могут писать код типа

MyClass bar = new MyClass();
bar.foo++;

теперь, если вы понимаете, что foo должен быть двойным, а не int, вы меняете его:

class MyClass {
    public double foo;
}

и код клиента не скомпилируется: - (

С хорошо спроектированным интерфейсом изменение внутренних элементов (частных частей) может даже включать включение переменной-члена в расчет или наоборот:

class Person {
    public String getName();
    public String getStreetAddress();
    public String getZipCode();
    public String getCountryCode();
    public int hashCode();
}

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

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

Вы также можете свободно решать, следует ли каждый раз вычислять хеш-код, или кэшировать его в приватную переменную, чтобы повысить производительность. Однако, если это поле кэша было общедоступным, любой может изменить его, что может испортить поведение карты хэша и ввести тонкие ошибки. Таким образом, инкапсуляция является ключом к обеспечению согласованности внутреннего состояния вашего объекта. Например. в приведенном выше примере ваши сеттеры могут легко проверить почтовый индекс и код страны, чтобы предотвратить установку недопустимых значений. Вы даже можете убедиться, что формат почтового индекса действителен для фактической страны, то есть обеспечить критерии достоверности, охватывающие несколько свойств. С хорошо спроектированным интерфейсом вы можете принудительно выполнить привязку, например. предоставляя только установщик для одновременного установки обоих свойств:

    public void setCountryCodeAndZip(String countryCode, String zipCode);

Однако в публичных полях у вас просто нет этих вариантов.

Специальный прецедент для частных полей - неизменяемые объекты; это очень часто встречается в Java, примеры String и BigDecimal. Эти классы вообще не имеют публичных разработчиков, что гарантирует, что их объекты, созданные после их создания, не изменят свое состояние. Это обеспечивает большую оптимизацию производительности, а также упрощает их использование, например. многопоточные программы, ORM и т.д.

Ответ 2

Возможно, вы захотите прочитать Информационное сокрытие в википедии.

По сути, частные члены позволяют классу скрывать детали реализации от внешних потребителей.. Это позволяет классу лучше контролировать, как будут отображаться данные и поведение, и позволяет потребителю не знать детали, которые не имеют отношения к основной цели класса.

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

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

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

Ответ 3

Хорошо объяснено в Раздел 7.4: Защитите свои частные части этого онлайн-учебник по С++.

Зачем беспокоиться об этом?

Спецификаторы позволяют классу быть очень комплекс, со многими функциями-членами и членов данных, имея простой публичный интерфейс, который другой классы могут использовать. Класс, который имеет два сто членов данных и сто функции-члены могут быть очень сложно писать; но если есть только три или четыре общественных члена функции, а остальные - все личное, кому-то может быть легко узнайте, как использовать класс. Он только необходимо понять, как использовать небольшой несколько публичных функций и не нужно беспокоиться о двух сотни членов данных, потому что он не позволило получить доступ к этим данным. Он может только доступ к частным данным через открытый интерфейс класса. Без сомнения, в небольшой программе, используя эти спецификаторы могут казаться ненужными. Однако они ценят понимание если вы планируете выполнять любую программу разумный размер (более пары сто строк). В общем, это хорошо чтобы частные члены данных были закрыты. Функции членов, которые должны быть вызваны извне класс должен быть публичные и членские функции, которые только вызываемый из класса (также известный как "вспомогательные функции" ) вероятно, должны быть частными. Эти спецификаторы особенно полезны в большая программа, включающая более одного программист.

В приведенном выше объяснении объясняется, как использование private облегчает кривую обучения. Вот пример, который объясняет аспект "нарушения кода":

Здесь класс ParameterIO, который считывает и записывает вектор целочисленных параметров

class ParameterIO
{
public:
    // Main member
    vector<int> *Params;
    string param_path;

    // Generate path
    void GeneratePath()
    {       
        char szPath[MAX_PATH];
        sprintf(szPath,"params_%d.dat",Params->size());
        param_path = szPath;
    }

    // Write to file
    void WriteParams()
    {
        assert_this(!Params->empty(),"Parameter vector is empty!");
        ofstream fout(param_path.c_str());
        assert_this(!fout.fail(),"Unable to open file for writing ...");
        copy(Params->begin(),Params->end(),ostream_iterator<int>(fout,"\n"));
        fout.close();
    }

    // Read parameters
    void ReadParams(const size_t Param_Size)
    {
        // Get the path
        Params->resize(Param_Size);
        GeneratePath();
        // Read
        ifstream fin(param_path.c_str());
        assert_this(!fin.fail(),"Unable to open file for reading ...");
        // Temporary integer
        for(size_t i = 0; i < Params->size() && !fin.eof() ; ++i) fin>>(*Params)[i];
        fin.close();
    }

    // Constructor
    ParameterIO(vector<int> * params):Params(params)
    {
        GeneratePath();
    }

    // Destructor
    ~ParameterIO()
    {
    }      

    // Assert
    void assert_this(const bool assertion, string msg)
    {
        if(assertion == false) 
        {
            cout<<msg<<endl;
            exit(1);
        }
    }
};

Следующий код разбивает этот класс:

const size_t len = 20;
vector<int> dummy(len);
for(size_t i = 0; i < len; ++i) dummy[i] = static_cast<int>(i);
ParameterIO writer(&dummy);

// ParameterIO breaks here!
// param_path should be private because 
    // the design of ParameterIO requires a standardized path
writer.param_path = "my_cool_path.dat";
// Write parameters to custom path
writer.WriteParams();

vector<int> dunce;
ParameterIO reader(&dunce);
// There is no such file!
reader.ReadParams(len);

Ответ 4

Это действительно зависит от вашей идеологии. Идея состоит в том, чтобы скрыть информацию, которая не должна быть раскрыта по какой-либо причине.

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

Кроме того, в Java, например, у вас нет возможности ограничить доступ к переменной-члену без изменения ее видимости, поэтому вы часто оказываетесь преждевременно создающим геттеры и сеттеры и делая эту переменную самой частной или защищенной. В Python, например, эта проблема не существует, потому что вы можете заставить геттеры и сеттеры вести себя как переменные для прямого доступа (они называются свойствами там).

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

Правило большого пальца: если вы что-то выставляете, кто-то его будет использовать. И чаще всего они будут использовать его по неправильным причинам (т.е. Не так, как вы планировали использовать их). В этом случае "Информационное сокрытие" является эквивалентом детских замков на шкафах оружия.

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

Каковы цели наличия внутренних органов в организме человека? Какой вред в том, что все органы снаружи?

Точно!

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

Ответ 9

Никакого вреда в зависимости от аудитории и потребления этого класса. Позвольте мне повторить, что еще раз, чтобы он погрузился.

Никакого вреда в зависимости от аудитории и потребления этого класса.

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

Итак, вам действительно нужно посмотреть, как класс будет потребляться, и кем вы еще не можете начать отвечать на этот вопрос. Аналогично, как долго будет длиться жизненный цикл разработки программного обеспечения? Это месяцы? Много лет? Десятилетия? Будут ли другие люди, кроме вас, используя класс?

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

Ответ 10

Краткий пример: вам может потребоваться определенные условия для этого значения. В этом случае установка его напрямую может нарушить такое условие.

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