Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Объясните пожалуйста про инкапсуляцию


Автор: Furchtlos 23.11.2011, 19:48
Не могу понять ДЛЯ ЧЕГО она нужна? Везде твердят примерно одно и то-же. Инкапсуляция связывает код и данные, и скрывает ненужный код и данные от пользователя а также защищает код от неправильного использования(это писал по памяти). Определение запомнил. А понять не могу. Каким образом можно неправильно использовать код? Приведите пожалуйста пример РЕАЛЬНОГО преимущества инкапсуляции. Левый пример про автомобиль и например давление в камере сгорания прошу не приводить, т.к обычный юзер может залезть в двигло и покопаться, естесственно что он может его обратно и не собрать, однако залезть в двигатель, мне кажется, намного легче, чем каким-то образом влезть в код(поправьте, если не прав). Также что конкретно означает понятие "интерфейс"? Это то, что взаимодействует с юзером? Т.е все эти сообщения в окне, и то, что туда можно вводить? Ок, тогда почему не написать код, чтобы юзер не мог уничтожить данные? В общем я слегка начал это понимать когда увидел пример про файловую систему. Т.е чтобы обратиться в файловую систему через, например, C++ мы используем специальные функции, а не обращаемся напрямую. Т.е инкапсуляция ограничивает наши возможности в данном случае. Ну а что значит тогда обращаться "напрямую"? Нашел на википедии пример кода для C#:
Код

class EncapsulationExample
{
private double valueDouble;
private string valueString;

public double Value
{
get { return valueDouble; }
set 
{
valueDouble = value;
valueString = value.ToString();
}
}

public string ValueString
{
get { return valueString; }
set 
{
double tmp_value = Convert.ToDouble(value); //здесь может возникнуть исключение
valueDouble = tmp_value;
valueString = value;
}
}
}

Но я не понял тут что значит например "public double Value"? Это поле класса? Если так, то почему оно похоже на метод? Что значит это "value" с маленькой буквы? Оно нигде не объявлено, это то значение, которое мы можем задать нашей "double Value" посредством метода "set"? Зачем внизу создается временная переменная "tmp_value"? Если можно было-бы сразу запихнуть в "valueDouble" значение "Convert.ToDouble(value)". И какое тут может возникнуть исключение? Не правильное приведение типа? А какой тип мы можем сюда неправильно засунуть? Так, чтобы компилятор запустил все это? Заранее благодарю!

Автор: newbee 23.11.2011, 20:13
Инкапсуляция в широком смысле означает скрытие множества сущностей и связей между ними за термином одной сущности. Например автомобиль инкапсулирует в себе четыре колеса, руль, сидение и механизм управления колесами рулем. Они в свою очередь тоже инкапсулируют что-то и так до разумных пределов. В программировании смысл инкапсуляции такой же: ты разбиваешь задачу на множество подзадач и объектов, связываешь и манипулируешь ими. Например в задаче упрощенного моделирования движения автомобиля ты только автомобилю "скажешь" переместиться на сто метров вперед, а весь свой хлам внутри включая человеков он передвинет сам.

Добавлено через 1 минуту и 12 секунд
Исходник я конечно не читала. Его тебе кто-нибудь другой объяснит.

Автор: Furchtlos 23.11.2011, 20:18
Это я понимаю, что скрывает. Но каким образом можно навредить коду, не скрыв?

Автор: newbee 23.11.2011, 20:32
Цитата(Furchtlos @  23.11.2011,  21:18 Найти цитируемый пост)
Но каким образом можно навредить коду, не скрыв? 
Это в первую очередь вопрос удобства. Но повредить тоже можно. Вот есть у объекта двигатель функция "включить", внутри она что-то делает и выставляет флаг "включен". По этому флагу ты всегда можешь узнать, жужжит в данный момент мотор или нет. А теперь мы берем и снаружи этого объекта выставляем флаг в "выкл". В лучшем случае мы просто будем получать недостоверную информацию о состоянии мотора, а в худшем во время повторного вызова функции "включить" она попытается завести уже работающий мотор, в процессе что-нибудь пойдет не так и ба-бах! Кровь, сопли, кишки, слезы!

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

Автор: Furchtlos 23.11.2011, 20:38
Как пользователь может сломать состояние объекта? Вводом неправильных данных?

Автор: newbee 23.11.2011, 20:43
Ну и дополню себя же любимую. Именно скрытие - в том смысле, что до каких-то частей объекта нельзя получить доступ - это не инкапсуляция, а просто эдакое дополнение к ней. Непосредственно инкапсуляция подразумевает именно составление совокупностей объектов и работа с совокупностью как с единым объектом. Есть такое понятие - системный подход, это из области методов исследований. Вот инкапсуляция как раз лежит в его основе.

Добавлено через 1 минуту и 7 секунд
Цитата(Furchtlos @  23.11.2011,  21:38 Найти цитируемый пост)
Как пользователь может сломать состояние объекта? Вводом неправильных данных? 
smile Под пользователем у тебя подразумевается не чувак, тыкающий кнопки на экране, а сторонний программист, который использует чужую библиотеку/код.

Автор: Furchtlos 23.11.2011, 20:54
Это уже совсем другое дело.Большое спасибо! Всё-равно осталось не совсем ясно, но теперь с другой стороны.

Автор: bsa 23.11.2011, 21:03

M
bsa
Furchtlos, если ответ на вопрос получен, то пометь тему решенной

Автор: mes 23.11.2011, 22:34
Код

struct string 
{
     size_t  size;
     char * data;
};

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

class string
{
           size_t get_size () const;
           void change (const char* str ) 
           {
                    _size = strlen (str);
                   _data = strcopy (str);
           }
  private:  // 
           size_t  _size;
           char * _data;
};

мы можем получить, но не изменить размер отдельно от изменения  строки данных.. 

Автор: Furchtlos 23.11.2011, 23:42
А зачем тут нужны константы?

Автор: mes 24.11.2011, 00:11
Цитата(Furchtlos @  23.11.2011,  22:42 Найти цитируемый пост)
А зачем тут нужны константы? 

в методе get квалификатор неизменности состояния объекта.. (т.е. можно только запросить данные но не изменить)
const char *  -  си-строка

Автор: Lols 24.11.2011, 03:07
1. напрягать пользователя ответсвенностью за каждое изменение
а мне вот этот вариант больше нравится...

Автор: mes 24.11.2011, 09:52
Lols,  С (не C++) как раз  того и предлагает.. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)