Представитель Шуры Люберецкого в ЖЖ (brat_luber) wrote,
Представитель Шуры Люберецкого в ЖЖ
brat_luber

ООП и структурки

В очередной раз прочитал в качестве определения “объектно-ориентированности” что-то типа “это структурки и код для работы с ними“. Удивительно, как популярная (но не единственная) реализация так повлияла на понимание термина. Речь идет прежде всего о том, как “объектно-ориентированность” реализована в C++.

Для начала – попытаемся понять, что же такое “объектно-ориентированность” в программировании. Мне очень нравится определение из SICP:

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

Таким образом, способ, которым мы организуем большую программу, в значительной степени диктуется нашим восприятием моделируемой системы. В этой главе (3 глава SICP) мы исследуем две важных организационных структуры, которые соответствуют двум достаточно различным взглядам на мир и структуру систем. Первая из них сосредотачивается на объектах (objects) и большая система рассматривается как собрание индивидуальных объектов, поведение которых может меняться со временем.

Объектно-ориентированное программирование (а точнее, проектирование) в классическом его понимании – это представление “предметной области” в виде множества объектов, каждый из которых обладает своим внутренним состоянием. В том же классическом представлении предполагается, что объекты могут обмениваться сообщениями – и изменяют свое состояние только реагируя на эти сообщения.

Эта модель в явной форме была реализована в языках типа Simula или Smalltalk. Из более современного можно назвать, например, VRML – это не просто “формат файлов” типа Autocad или 3D Studio, а практически полноценная реализация вышеназванного принципа. Из “настоящих” языков программирования – можно привести в качестве примера Objective C. Очень похожи на модель с обменом сообщениями “сигналы” и “слоты” библиотеки Qt – но в данном случае речь идет о диком смешении двух подходов к ООП, и вряд ли это стоит считать подходящим примером.

Па-а-азвольте, скажут тут знатоки современных языков программирования – где же тут private и public переменные, где здесь методы? И вот тут придется вспомнить про то, что C++ – первый широко используемый “объектно-ориентированный” язык, но создавался он исключительно как “C с классами”, причем эти “классы”, как и все объектно-ориентированные возможности раннего C++, были лишь имитацией таких возможностей в “настоящих” объектно-ориентированных языках.

Важно понимать, что “вызов метода” в C++ – это лишь реализация “передачи сообщения” от одного объекта другому. Фактически, в C++ вместо передачи сообщений используются три разных “примитива”. Например, возьмем вот такой класс:

class A {
public:
	int x;
	int f(int y);
private:
	int z;
};

… и вот такой код, работающий с ним:

A a;
int b;
a.x = 2;
b = a.x;
b = a.f(3);

В С++ эти три строчки – принципиально разные операции. На самом деле все они могут быть рассмотрены, как частный случай “посылки сообщения” (а ее мы будем записывать в виде адресат.сообщение(аргументы)):

class A {
public:
	int get_x();
	void set_x(int new_x);
	int f(int y);
private:
	int x, z;
};

... 

A a;
int b;
a.set_x(2);
b = a.get_x();
b = a.f(3);

Замечу, что “накладные расходы” второго способа оказываются несколько больше. Но “идеологически” и присваивание, и чтение значения, и вызов метода – это одна и та же операция. Все переменные-члены класса перемещаются в секцию private – и состояние объекта действительно становится “внутренним”.

В “настоящих” объектно-ориентированных языках, типа Smalltalk, с помощью модели передачи сообщений реализовывались даже такие вещи, как индексация массивов или циклы. В принципе, несложно подобным образом реализовать и арифметические вычисления – с помощью каких-нибудь специально созданных объектов, типа “сумма” (я тут перейду на “русский” псевдокод):

объект Формула {
методы:
	Число вычислить() - чисто виртуальный;
}

объект Сумма : Формула {
методы:
	Число вычислить();
	задатьПервоеСлагаемое();
	задатьВтороеСлагаемое();
переменные состояния:
	Формула первоеСлагаемое, второеСлагаемое;
}

объект Константа : Формула {
методы:
	Число вычислить();
	задатьЗначение(Число);
переменные состояния:
	Число значение;
}

Думаю, что реализации расписывать не надо? А вот как это можно использовать:

Константа к1, к2, к3;
Сумма с1, с2;
Число результат;
к1.задатьЗначение(1);
к2.задатьЗначение(2);
к3.задатьЗначение(3);
с1.задатьПервоеСлагаемое(к1);
с1.задатьВтороеСлагаемое(к2);
с2.задатьПервоеСлагаемое(с1);
с2.задатьВтороеСлагаемое(к3);
результат = с2.вычислить();

Естественно, что вышеописанное – это некоторое извращение, и все соответствующие объекты должны создаваться сразу, как только мы напишем результат = (1+2)+3;. “Метод” в нашей терминологии – это не более чем описание “формата” получаемого сообщения и реакции на него.

С++ – это попытка “приделать” объекты к существующему “необъектному” языку C. В C уже были и структурки, и функции – именно поэтому в C++ “классы” – это некоторое обобщение структур C. После того, как C++ стал действительно распространен – аналогичный подход “взяли на вооружение” разработчики других языков. Именно поэтому в “современном” ООП практически нельзя встретить “чистую” передачу сообщений – только подход “объект – это данные плюс функции”.

Жутким монстром на фоне этого всего выглядит Qt – где умудрились объединить и обмен сообщениями (в виде сигналов и слотов), и “объекты в стиле C++”. Получилось что-то в духе чудовища Франкенштейна – хотя иногда и довольно удобное в использовании.

Запись опубликована в блоге Шуры Люберецкого. Вы можете оставлять свои комментарии там, используя свое имя пользователя из ЖЖ (вход по OpenID).

Tags: программирование
Subscribe

  • Таджикоанглийский

    Один ли я, читая Release Notes на этой картинке, вспоминаю Равшана и Джамшута? Запись опубликована в блоге Шуры Люберецкого. Вы можете…

  • Вдогонку истории про Кинопоиск

    Почитал комментарии к “перезапуску” Яндексом Кинопоиска. Что хочу сказать? Яндексовцы сделали просто офигенный и современный “сайт…

  • И еще вдогонку

    Вот обсуждают все пресловутый флешмоб “про 90-е”. Кто-то честно выкладывает фоточки “из детства”, кто-то – истории про…

Comments for this post were disabled by the author