OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 10 Декабрь, 2024 20:25

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 4 ] 
Автор Сообщение
 Заголовок сообщения: А как тут с объектами?
СообщениеДобавлено: Среда, 03 Октябрь, 2007 22:54 

Зарегистрирован: Среда, 03 Октябрь, 2007 11:03
Сообщения: 2
Я сам программирую в основном в 1С, но немного знаю С++. Прочитал описание Компонентного Паскаля, но в нем весьма поверхностно коснулись всего что связано с ООП. Где найти более подробное описание желателлльно с примерами? И и чем собственно компонент-ориентированное программирование отличается от объектно ориентированного?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: А как тут с объектами?
СообщениеДобавлено: Среда, 03 Октябрь, 2007 23:00 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Попробуйте почитать материалы отсюда:
http://oberoncore.ru/index.php?option=c ... &Itemid=22
http://wiki.oberoncore.ru/index.php/Технические_решения

Что будет непонятно, спрашивайте :-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: А как тут с объектами?
СообщениеДобавлено: Четверг, 04 Октябрь, 2007 10:09 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2459
Откуда: Россия, Томск
Любой RECORD является объектом, если к нему добавить методы, т.е. "связанные процедуры". Пример:
Код:
TYPE Object = POINTER TO EXTENSIBLE RECORD x, y: INTEGER END;
PROCEDURE (self: Object) SetCoords* (x, y: INTEGER), NEW;
BEGIN
   self.x := x;
   self.y := y
END SetCoords;

Наследование называется "расширением типа" (type extension). Пример:
Код:
TYPE ExtendedObject = POINTER TO EXTENSIBLE RECORD (Object) z: INTEGER END;
PROCEDURE (self: ExtendedObject) SetAll (x, y, z: INTEGER), NEW;
BEGIN
   self.SetCoords(x, y);
   self.z := z
END SetAll;

Если какой-то тип хотите сделать нерасширяемым (final), не указывайте слово EXTENSIBLE.

Хорошее описание языка и ООП с примерами есть в книге Вирта "Programming in Oberon", см. последюю главу. Там и шина сообщений описана. Немногочисленные отличия Компонентного Паскаля от Оберона описаны в документе Docu/CP-New.odc в любом комплекте Блэкбокса.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: А как тут с объектами?
СообщениеДобавлено: Четверг, 04 Октябрь, 2007 21:18 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2935
Откуда: г. Ярославль
А вот и последняя глава 23.4 книги "Programming in Oberon". Позволю себе представить собственный перевод, сделанный исключительно для себя - чтоб лучше "въехать" в тему :)

Programming in Oberon

A derivative of Programming in Modula-2 (1982)
Niklaus Wirth

23.4. Обработчики и сообщения.

В разделе 3 была подчёркнута важность правильной декомпозиции (модуляризации) систем. Модуль ограничивает видимость объявлений и включает в себя концепцию скрытия информации. В объектно-ориентированных языках определение типа, то есть объявление класса, принимает на себя как роль модуля, так и роль единицы раздельной компиляции. В Обероне мы предпочитаем отделять конструкции, выражающие скрытие информации, от конструкций для определения типов и процедур.
Таким образом, модуль может содержать одно или несколько определений типов, или же не содержать ни одного. Тем не менее, взгляд на тип данных и его операторы как на логическую единицу, скрывающую детали реализации, является старой и проверенной практикой в концепции абстрактного типа данных.
В частности, для сложных объектов требуется, чтобы различные подтипы могли быть определены и реализованы отдельными командами программистов, и могут пройти годы от определения базисной части до опубликования или дистрибуции. Нужно иметь возможность определять каждый производный тип в его собственном модуле. Это необходимо как для базовых типов с операциями, применяемыми ко множеству объектов (в отличие от отдельных объектов), определённых в базовом модуле, так и для определений производных типов в клиентских модулях.
Среди таких операций мы выделяем так называемое широковещание (broadcast), то есть, обход структуры, содержащей объекты (список, дерево) с применением метода к каждому элементу. Объявление таких бродкастов в основе своей ограничено базовым модулем.
Однако, подтип может вводить особые операции, в том числе и такие, которые не доступны другим подтипам. Очевидно, что такие операции должны выполниться при бродкасте, процедура которого определена в базовом модуле, даже если новые операции введены спустя годы после определения базовой функциональности. Базовые определения, однако, не могут быть ни изменены, ни открыты для доступа, потому что они уже давно распределены по клиентуре. Как же разрешить эту дилемму?
Решение заключено в замене набора методов одной-единственной процедурой, которая выделяется среди других методов. Такую процедуру мы назовём обработчиком (handler). Обработчик имеет только два параметра: объект, к которому он применяется и идентификатор операции с соответствущими параметрами. Второй параметр обработчика имеет форму записи (record) и мы назовём его сообщение. Сообщение может обозначать любую операцию, даже вводимую в будущем. Такая возможность используется для введения новых, производных типов, и называется оно «расширение типа» (type extension). Позвольте объяснить это решение на примере графического редактора.

Во-первых, объявим базовый тип следующим образом:

Код:
FigureDesc = RECORD
  x, y, w, h: INTEGER;  (*координаты, ширина и высота объекта*)
  handle: Handler;
  next: Figure   (*следующий элемент в списке объектов*)
END ;


Процедурный тип Обработчик объявим так:

Код:
Handler = PROCEDURE (f: Figure; VAR msg: Message)

и новый тип Сообщение, как пустую и расширяемую запись:

Код:
Message = RECORD END


Если какие-то операции, применяемые ко всем объектам, уже известны в момент определения базового типа, то подтипы нашего сообщения объявляются примерно так:

Код:
DrawMsg  =  RECORD (Message) END ;
MarkMsg  =  RECORD (Message) on: BOOLEAN END ;
MoveMsg  =  RECORD (Message) dx, dy: INTEGER END ;


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

Код:
PROCEDURE Broadcast(VAR msg: Message);
  VAR f: Figure;
BEGIN f := root;  (*root – глобальная переменная в базовом модуле*)
  WHILE f # NIL DO f.handle(f, msg); f := f.next END
END Broadcast

Любой новый подтип фигуры будет определён в новом клиентском модуле, импортирующем базовый модуль Figures. С определением нового подтипа будет ассоциирован обработчик, шаблон объявления которого приведён ниже. Этот обработчик инсталлируется в поле handle каждого объекта типа Rectangle.

Код:
PROCEDURE Handle(f: Figure; VAR msg: Message);
VAR r: Rectangle;
BEGIN r := f(Rectangle);
  IF msg IS DrawMsg THEN  (*нарисовать прямоугольник r*)
  ELSIF msg IS MarkMsg THEN MarkRectangle(r, msg(MarkMsg).on)
  ELSIF msg IS MoveMsg THEN
    INC(r.x, msg(MoveMsg).x); INC(r.y, msg(MoveMsg).y)
  ELSIF …
  END
END Handle


Операция перемещения объекта путём указания смещения dX и dY выглядит как нечто составное:

Код:
VAR msg: MoveMsg;
msg.dx := dX; msg.dy := dY; f.handle(f, msg)

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

Код:
msg.dx := dX; msg.dy := dY; Broadcast(msg)


Особая гибкость этой техники, использующей обработчики и сообщения, иногда определяется как полиморфизм, поскольку расширяемость опирается на тот факт, что «неизвестные» сообщения попросту игнорируются. Они «проваливаются» через каскад конструкции if – elsif в обработчике объекта, которому сообщение не предназначено.
Для примера, к нашему редактору добавим новый модуль, и назовём его Blinkers. Он содержит объявление производного типа Blinker ( BlinkerDesc), в котором введён новый метод, заставляющий объект мерцать в заданном ритме. Нам понадобится производное сообщение BlinkMsg. Вызов обработчика любого другого объекта в глобальном списке объектов, через который распространяются сообщения, не приведёт ни к какому эффекту, поскольку конструкция

Код:
ELSIF msg IS BlinkMsg THEN …


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

Подводя итоги, можно сказать следующее:

1.Объект представлен как указатель на запись. Запись содержит процедурное поле, называемое handle. Процедура, присвоенная этому полю, называется обработчиком и принимает два параметра. Первый параметр определяет объект, чей обработчик вызывается. Второй параметр определяет операцию, это параметр VAR, является записью и называется сообщением.
2.Обработчик задаёт поведение объекта и вызывается посредством сообщения, которое обычно является специфичным для данного объекта расширением типа Message.
3.Сообщение, передаваемое как параметр, указывает действие, относящееся к его типу. Поля записи сообщения составляют параметры действия. Их количество и типы специфичны для конкретного типа сообщения и действия.
4.Обработчик содержит каскад if – elsif. Проверки типов позволяют разделить подтипы сообщений и соответствующие им действия.
5.Присвоение обработчика объекту называется инсталлированием.
6.Действие осуществляется, во-первых, установкой параметра сообщения, а во-вторых, посылкой сообщения объекту.
7.Сообщения распространяются широковещательным способом всем объектам, имеющим разнородные структуры данных, причём знать природу этой структуры не нужно. Неподходящие сообщения просто игнорируются.

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

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

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


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 4 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB