Основная проблема здесь заключается в том, что инкапсуляция не является жестко определенным понятием, и почему это не полезно. Проведение некоторых исследований показывает, что то, как люди видят инкапсуляцию, очень самоуверенно, и что многие люди путают ее с абстракцией.
Первое определение, которое вы найдете, это
Инкапсуляция - это концепция, которая связывает воедино данные и функции, которые манипулируют данными ...
Если это ваше определение, то большинство языков имеют возможность группировать данные и функции, работающие с этими данными, в классы, модули, библиотеки, пространства имен и т. Д.
Но я бы сказал, что это не главная цель инкапсуляции, поскольку это определение продолжается:
... и это защищает как от постороннего вмешательства, так и от неправильного использования.
Википедия также соглашается с этим:
Языковой механизм для ограничения прямого доступа к некоторым компонентам объекта.
Но теперь нам нужно спросить, что подразумевается под «вмешательством и неправильным использованием» и почему должен быть ограничен прямой доступ к данным. Я считаю, что есть две причины.
Во-первых, это ограничивающая область, в которой данные могут быть изменены, в интересах разработчика. Слишком часто возникает необходимость в логике до / после установки значения. И иметь ограниченное количество мест, где можно установить значение, чрезвычайно ценно. На языках ООП это можно сделать с помощью классов. В «изменчивых» функциональных языках замыкания служат той же цели. И потому , что мы знаем классы = замыкания , это даже спорно , чем изменяемые функциональные языки отличаются «парадигма» ООП.
Но как насчет неизменных языков? Это не проблема мутирующих переменных. Вот тут и возникает вторая проблема: связывание функций и данных позволяет поддерживать эти данные в состоянии, которое является действительным. Представьте, что у вас есть неизменяемая структура Email
. Эта структура имеет одно string
поле. У нас есть требования, что если у вас есть значение типа, Email
то это поле содержит действительный адрес. В инкапсуляции ООП это легко сделать, объявив это поле private
, предоставив только Get
метод иconstructor method
это только успешно, если передано в строке является действительным адресом. Аналогичная вещь с замыканиями. Теперь для неизменяемого языка нужно сказать, что структура может быть инициализирована только через определенную функцию, и такая функция может потерпеть неудачу. И я не знаю ни одного языка, который бы соответствовал этим критериям (возможно, кто-то в комментариях может просветить меня).
Последняя проблема заключается в том, что подразумевается под языком «поддерживающей» инкапсуляции. С одной стороны, есть языки, которые позволяют применять инкапсуляцию, чтобы код не компилировался, если инкапсуляция нарушена. С другой стороны, язык может обеспечить способ инкапсуляции, но он не обеспечивает его выполнение, оставляя разработчику возможность применять его самостоятельно. Во втором случае может работать любой язык, имеющий структуры и функции. Динамические языки и Haskell приходят на ум. И я бы сказал, что на другой стороне спектра не так много языков. Даже C #, который действительно хорош в обеспечении инкапсуляции для своих объектов, можно обойти с помощью отражения. Но, увидев это в C #, можно было бы считать массивным запахом кода, и ни один здравомыслящий C # разработчик не сделал бы этого охотно.