вторник, 16 мая 2017 г.

Кто такой объект?

Существуют тысячи книг по объектно-ориентированному программированию и сотни объектно-ориентированных языков, и я считаю, что большинство (читайте «все») из них дают неправильное определение «объекта». Вот почему весь мир ООП настолько полон заблуждений и ошибок. Их определение объекта ограничено аппаратной архитектурой, с которой они работают, и поэтому очень примитивно и механично. Я хотел бы представить более подходящий вариант.




Что такое объект? Я провел небольшое исследование, и вот что я нашел:

«Объекты могут содержать данные в форме полей, часто называемых атрибутами, и код в виде процедур, часто называемых методами», Википедия.

«Объект сохраняет свое состояние в полях и раскрывает его поведение с помощью методов» -Что такое объект? Oracle.

«Каждый объект выглядит совсем как маленький компьютер - у него есть состояние, и у него есть операции, которые вы можете попросить его выполнить», - размышляет в Java, 4-е изд., Брюс Эккель, с. 16.

«Класс - это набор полей данных, в которых хранятся значения и методы, которые оперируют этими значениями» -Java в двух словах, 6-е изд., Evans и Flanagan, p. 98.

«Объект - это некоторая память, которая содержит значение некоторого типа» - Язык программирования C ++, 4th Ed., Bjarne Stroustrup, p. 40.

«Объект состоит из некоторой частной памяти и набора операций» -Smalltalk-80, Goldberg and Robson, p. 6.

Общим для всех этих определений является слово «содержит» (или «содержит», «состоит», «имеет» и т.д.). Они все думают, что объект - это коробка с данными. И это именно то, против чего я категорически против.

Если мы посмотрим, как реализуются C++ или Java, такое определение объекта будет звучать технически корректно. Действительно, для каждого объекта виртуальная машина Java выделяет несколько байтов в памяти, чтобы хранить там атрибуты объектов. Таким образом, мы можем с технической точки зрения сказать на этом языке, что объект является полем памяти с данными.

Правильно, но это всего лишь примитивный случай!

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

c {
  vin: v,
  engine: e
}

Здесь, vin и engine являются атрибутами объекта c (это автомобиль, давайте забудем о классах, чтобы теперь сосредоточиться строго на объектах). Таким образом, существует простой объект, который имеет два атрибута. Первый - это VIN автомобиля, а второй - его двигатель. VIN является объектом v, а движок e. Чтобы было проще понять, как выглядит похожий объект в Java:

Char [] v = {'W', 'D', 'B', 'H', ... '7', '2', '8', '8'}; // 17 символов
Двигатель e = новый двигатель ();
Автомобиль c = новый автомобиль (v, e);

Я не совсем уверен в JVM, но в C++ такой объект займет ровно 25 байт в памяти (при условии, что это 64-битная архитектура x86). Первые 17 байтов будут приняты массивом символов и еще 8 байтов указателем на блок в памяти с объектом e. Именно так компилятор C++ понимает объекты и переводит их в архитектуру x86. В C ++ объекты - это просто структуры данных с четко определенным распределением атрибутов данных.

В этом примере атрибуты vin и engine не равны: vin - это «данные», а engine - «указатель» на другой объект. Я намеренно сделал это таким образом, чтобы продемонстрировать, что вызов объекта полем с данными возможен только с помощью vin. Только когда данные расположены «внутри» объекта, мы можем сказать, что объект на самом деле является полем для данных. С двигателем это не совсем так, потому что в объекте нет данных технически. Вместо этого есть указатель на другой объект. Если бы наш объект имел только атрибут engine, он занимал бы всего 8 байт в памяти, причем ни один из них фактически не занимался «данными».

Объекты больше не являются полями с данными; Они знают, где находятся данные, но они не содержат данных

Теперь давайте вернемся к нашему новому псевдоязыку. Представим, что он относится к объектам совсем иначе, чем к C ++ - он не сохраняет атрибуты объектов в памяти вообще. У него нет указателей, и он ничего не знает о архитектуре x86. Он просто каким-то образом знает, какие атрибуты принадлежат объекту.

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

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

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

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

Кстати, вот определение объекта из моей любимой книги «Объектное мышление» Дэвида Уэста, с. 66:

Объект - это эквивалент квантов, из которых строится вселенная

Насколько это близко к «представительному» определению, которое я только что предложил?

Комментариев нет:

Отправить комментарий