Ответ 1
OO Abstraction возникает во время разработки уровня класса с целью скрывать сложность реализациинасколько понятны функции, предлагаемые API/дизайном/системой, в некотором смысле упрощая "интерфейс" для доступа к базовой реализации.
Этот процесс может повторяться со все более "высшими" уровнями (уровнями) абстракции, что позволяет строить большие системы без увеличения сложности кода и понимания на более высоких уровнях.
Например, разработчик Java может использовать функции высокого уровня FileInputStream, не заботясь о том, как это работает (например, файлы, проверки безопасности файловой системы, распределение памяти и буферизация будут управляться внутренне и скрыты от потребителей). Это позволяет изменить реализацию FileInputStream
, и пока API (интерфейс) до FileInputStream
остается неизменным, код, построенный против предыдущих версий, по-прежнему будет работать.
Аналогично, при проектировании ваших классов вы захотите скрыть внутреннюю реализацию от других, насколько это возможно.
В определении Booch 1 достигается OO Encapsulation посредством Сокрытие информации, и особенно вокруг скрытия внутренних данных (полей/членов, представляющих состояние), принадлежащих экземпляру класса, путем принудительного доступа к внутренним данным контролируемым образом и предотвращения прямого внешнего изменения этих полей, а также скрытия любых внутренних методов реализации класса (например, делая их частными).
Например, по умолчанию поля классов могут быть сделаны private
, и только если требуется внешний доступ к ним, будет ли отображаться get()
и/или set()
(или Property
) из класс. (В современных языках OO поля могут быть помечены как readonly
/final
/immutable
, что дополнительно ограничивает изменение даже внутри класса).
Пример, где НЕТ скрытия информации было применено (Плохая Практика):
class Foo {
// BAD - NOT Encapsulated - code external to the class can change this field directly
// Class Foo has no control over the range of values which could be set.
public int notEncapsulated;
}
Пример применения инкапсуляции полей:
class Bar {
// Improvement - access restricted only to this class
private int encapsulated;
// The state of Bar (and its fields) can now be changed in a controlled manner
public void setEncapsulatedField(int newValue) {
if (newValue < 100) {
encapsulated = newValue;
}
// else throw ... out of range
}
}
Пример инициализации неизменяемого/конструкторного поля:
class Baz {
private final int onlyValue;
public void Baz(int immutableValue) {
// ... can check that immutableValue is valid
onlyValue = immutableValue;
}
// Further change of `onlyValue` outside of the constructor is NOT permitted
// even within the same class
}
Re: Абстракция против абстрактного класса
Абстрактные классы - это классы, которые способствуют повторному использованию общности между классами, но которые сами не могут быть непосредственно созданы с помощью new()
- абстрактные классы должны быть подклассы, и могут быть созданы только concrete
(не абстрактные) подклассы. Вероятно, одним из источников путаницы между Abstraction
и abstract class
было то, что в первые дни OO наследование было более активно использовано для повторного использования кода (например, с ассоциированными абстрактными базовыми классами). В настоящее время композиция encapsulation
обычно используется в более общем смысле при определении того, какие методы, поля, свойства, события и др. bundle
в класс.
Цитата из Википедии:
В более конкретной настройке объектно-ориентированного языка программирования понятие используется как означающее либо механизм скрытия информации, механизм связывания, либо комбинацию двух.
Например, в заявлении "Я инкапсулировал код доступа к данным в свой собственный класс", интерпретация инкапсуляции примерно эквивалентна Разделение Обеспокоенность (S в SOLID) и, возможно, может использоваться как синоним рефакторинга.
[1] Как только вы увидите Booch инкапсулирование изображения кошки, вы никогда не сможете забыть инкапсуляцию - p46 объектно-ориентированного анализа и проектирования с приложениями, 2nd Ed