Что такое инкапсуляция?
У меня есть два определения инкапсуляции, которые не могут вписаться в одно определение.
- Инкапсуляция - это сокрытие данных. С использованием приватных, защищенных и общедоступных данных можно упаковать данные в один компонент.
- Какие бы изменения ни были заключены в капсулу. Защита всего, что подвержено изменениям.
Как эти два определения говорят об одном и том же понятии?
5 ответов
Инкапсуляция, вероятно, является наиболее неправильно понятой концепцией ООП.
Инкапсуляция НЕ скрывает данные!
"Инкапсуляция" происходит от "капсулы". Это означает собирать вещи вместе, заключать их в пакеты, и "вещи", о которых мы здесь говорим, - это данные и функции. Программирование без инкапсуляции означает, что функции, связанные с данными, "плавают вокруг" где-то в вашем коде, и хотя они имеют дело с вашими данными и даже принимают этот конкретный тип в качестве входных данных, они отделены от ваших данных.
Позвольте мне привести пример, не сосредотачиваясь на "общедоступных" и т. П.: если у вас есть класс, который имеет дело с комплексными числами, которые имеют действительную и мнимую часть, вы можете просто определить его следующим образом:
class complex {
double real;
double imaginary;
};
В старом стиле предварительной инкапсуляции, который использовался, например, в C, чтобы получить абсолютное значение этого числа, вы должны определить функцию, подобную этой:
double absolute(double real, double imaginary);
И это не будет связано с классом вообще! Конечно, вы также можете определить функцию, которая принимает комплекс классов в качестве входных данных, но она все равно будет внешней функцией. Таким образом, чтобы использовать его, вы должны сделать это:
complex A;
A.real = 1;
A.imaginary = -3;
и чтобы получить абсолютное значение, вы должны были бы позвонить
absolute(A.real, A.imaginary);
Вместо этого вы можете использовать инкапсуляцию и объединить данные и функции:
class complex {
double real;
double imaginary;
double absolute(); // inside the class, encapsulated into it!
};
а затем, чтобы получить абсолютное значение, вам просто нужно вызвать метод, как
A.absolute();
Это не требует скрытия данных вообще. Преимущество состоит в том, что код более управляем, потому что вы можете четко видеть все связанные "вещи" (то есть данные и функции), сгруппированные вместе, так что вы сразу узнаете, что у вас есть (данные) и что вы можете делать с это (методы).
Скрытие информации было бы невозможно без этого, потому что это означает, что вы ограничиваете доступ к некоторым членам (частным) извне, поэтому у вас должно быть несколько методов внутри, иначе вы не сможете ничего сделать с вашими данными!
В то же время сокрытие информации помогает эффективно использовать инкапсуляцию: если бы люди могли получить доступ к данным извне, было бы очень опасно иметь других кодеров, которые пишут свой собственный (не инкапсулированный) код для работы с вашими данными, что по крайней мере приведет к дублированию кода (т. е. бесполезным усилиям) и к несоответствиям, если реализации не будут полностью совместимы. Вместо этого скрытие данных означает, что для доступа к частным данным каждый ДОЛЖЕН использовать предоставленные публичные методы, чтобы они были одинаковыми для всех.
Таким образом, инкапсуляция необходима для сокрытия данных, чтобы иметь смысл, и в то же время ей помогает скрытие данных. Вместе они работают хорошо, но это не одно и то же!
Возвращаясь к вашему вопросу: в свете этого определение 1 неверно. И 2, как отмечает CommuSoft, на самом деле не является определением, это практическое правило. И я добавлю, что это практическое правило о том, когда использовать скрытие данных, а не инкапсуляцию.
С другой стороны, электрометро предполагает, что это может быть дубликатом этого вопроса. Я думаю, что стоит отметить, что большинство ответов там неправильные, включая верхний ответ, который дает пример инкапсуляции, которая на самом деле является противоположностью инкапсуляции.
Если вы хотите внешние ссылки, вот две статьи об этом:
Инкапсуляция не скрывает информацию
Абстракция, инкапсуляция и сокрытие информации (обратите внимание, что когда он начинает абзац под названием "ENCAPSULATION" и цитирует множество определений, он просто пытается показать путаницу вокруг этой темы; эти определения неверны, как он объяснит позже!)
Сокрытие данных о контроле. Когда вы скрываете данные, вы скрываете их от других программистов (в том числе и от вашего будущего), потому что они могут сделать что-то неправильно с данными, потому что они не знают об этом так много, как вы. Таким образом, вы хотите тщательно контролировать, как они используют данные - в этом случае, скрывая их, ограничивая доступ и видимость.
Инкапсуляция на самом деле не является практикой "защиты всего, что подвержено изменениям". Статьи, которые утверждают, что это чрезмерно обобщает, потому что большинство методов разработки программного обеспечения о "защите" вещей, которые мы могли бы изменить позже. Что вы должны знать, так это то, что часто бывает полезно изучить вещи, которые подвержены изменениям, и решить, какие ограничения вы хотите наложить на то, как другие люди видят и используют эти вещи, - как вы можете инкапсулировать эти вещи.
... Точно так же инкапсуляция также не является практикой "объединения функций с данными", как утверждают несколько статей, связанных в другом ответе. Подходящим термином для этого может быть модульность или простое старое объектно-ориентированное программирование - есть много связанных концепций. Эти методы могут привести к инкапсуляции, но называть их инкапсуляцией непонятно, особенно для начинающих. Инкапсуляция на самом деле о "сокрытии" данных. (Чтобы взять немного более сложный пример, в JavaScript вы можете поместить значение вместе с функцией либо как свойство объекта функции, либо с помощью замыкания. Ни одно из этих полей использования не включает использование методов класса / object / prototype, оба помещают данные и функцию "вместе", но только замыкание будет инкапсулировать данные, накладывая ограничения доступа.)
Цитируя Википедию:
"Инкапсуляция - это упаковка данных и функций в один компонент. Функции инкапсуляции поддерживаются с помощью классов в большинстве объектно-ориентированных языков программирования, хотя существуют и другие альтернативы.
В языках программирования инкапсуляция используется для обозначения одного из двух связанных, но различных понятий, а иногда и их комбинации:
Языковой механизм для ограничения доступа к некоторым компонентам объекта.
Языковая конструкция, которая облегчает связывание данных с методами (или другими функциями), работающими с этими данными ".
Я бы пошел со вторым в качестве определения инкапсуляции. Я вижу это так же. Инкапсуляция - это механизм защиты остальной части вашего кода от изменений.
Первое утверждение является более ограничительным. С помощью инкапсуляции вы скрываете не только данные, но и реализацию. А модификаторы видимости - это просто средство для получения инкапсуляции. Вы используете public для методов, к которым обращаются из других классов. Их изменение влияет на внешний код, который их вызывает. В то время как приватный скрывает вещи, которые вы не хотите, чтобы они были видны снаружи, и которые можно свободно изменять без влияния на другие классы.
Таким образом, второе утверждение является определением инкапсуляции, а первое - подсказкой о том, как его получить.
Инкапсуляция действительно скрывает данные. Причина состоит в том, чтобы сгруппировать аналогичные функции, которые могут измениться в будущем, гораздо более управляемым образом.
Инкапсуляция может быть достигнута гораздо большим, чем просто использование модификаторов видимости.