OberonCore
https://forum.oberoncore.ru/

Моделирование интерфейсов
https://forum.oberoncore.ru/viewtopic.php?f=29&t=3640
Страница 1 из 6

Автор:  Валерий Лаптев [ Понедельник, 31 Октябрь, 2011 11:27 ]
Заголовок сообщения:  Моделирование интерфейсов

В связи с исследованиями по семантическому редактору возник вопрос: А можно ли в Компонентном паскале промоделировать интерфейсы, как они сделаны в Яве и Додиезе.
Там они были придуманы, чтобы избавиться от множественного наследования классов. Зато класс может реализовать множество интерфейсов.
Мне пришла в голову мысль, что, может быть, модуль можно использовать в семантике интерфейса?

Автор:  Александр Ильин [ Понедельник, 31 Октябрь, 2011 11:34 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Валерий Лаптев писал(а):
А можно ли в Компонентном паскале промоделировать интерфейсы, как они сделаны в Яве и Додиезе.
Интерфейс - это абстрактная запись с набором опубликованных методов и скрытой ссылкой на экземпляр объекта.

Автор:  Сергей Губанов [ Понедельник, 31 Октябрь, 2011 11:48 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Валерий Лаптев писал(а):
Мне пришла в голову мысль...
Лучше скажите какую задачу Вам решить надо.

Автор:  Валерий Лаптев [ Понедельник, 31 Октябрь, 2011 11:56 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Александр Ильин писал(а):
Валерий Лаптев писал(а):
А можно ли в Компонентном паскале промоделировать интерфейсы, как они сделаны в Яве и Додиезе.
Интерфейс - это абстрактная запись с набором опубликованных методов и скрытой ссылкой на экземпляр объекта.

Это понятно. Но в КП нету ж множественного наследования. А интерфейсы в Яве и Додиезе решают проблему множественного наследования.

Автор:  Валерий Лаптев [ Понедельник, 31 Октябрь, 2011 11:58 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Сергей Губанов писал(а):
Валерий Лаптев писал(а):
Мне пришла в голову мысль...
Лучше скажите какую задачу Вам решить надо.

Как смоделировать множественное наследование?

Автор:  Сергей Губанов [ Понедельник, 31 Октябрь, 2011 12:03 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Валерий Лаптев писал(а):
Сергей Губанов писал(а):
Лучше скажите какую задачу Вам решить надо.

Как смоделировать множественное наследование?
Это всё?

Автор:  Александр Ильин [ Понедельник, 31 Октябрь, 2011 12:17 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Валерий Лаптев писал(а):
Александр Ильин писал(а):
Валерий Лаптев писал(а):
А можно ли в Компонентном паскале промоделировать интерфейсы, как они сделаны в Яве и Додиезе.
Интерфейс - это абстрактная запись с набором опубликованных методов и скрытой ссылкой на экземпляр объекта.

Это понятно. Но в КП нету ж множественного наследования. А интерфейсы в Яве и Додиезе решают проблему множественного наследования.
Не понял. В Яве тоже нет множественного наследования, и что?
Вы спросили, как промоделировать. Я вам ответил, как промоделировать. В терминах КП.

Автор:  Александр Ильин [ Понедельник, 31 Октябрь, 2011 12:27 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Код:
MODULE Interface;

(* Данный модуль содержит общее для системы определение интерфейса Writer.
 Для простоты интерфейс предоставляет единственный метод Write. *)

   TYPE
      Writer* = POINTER TO ABSTRACT RECORD
      END;

   PROCEDURE (w: Writer) Write* (), NEW, ABSTRACT;

END Interface.


MODULE Class;

(* Модуль Class содержит объект Object, поддерживающий интерфейс Interface.Writer. *)

   IMPORT
      Interface;

   TYPE
      Object* = POINTER TO RECORD
         writer-: Interface.Writer;
      END;

      ObjectWriter = POINTER TO RECORD (Interface.Writer)
         this: Object;
      END;

   PROCEDURE (ow: ObjectWriter) Write ();
      (** Реализация интерфейса Interface.Wirter для объекта Class.Object. *)
   BEGIN
      (* TODO: сохранить данные ow.this *)
   END Write;

   PROCEDURE NewObject* (): Object;
      (** Конструктор для типа Object. *)
      VAR
         ow: ObjectWriter;
         res: Object;
   BEGIN
      NEW(ow);
      NEW(res);
      ow.this := res;
      res.writer := ow;
      RETURN res
   END NewObject;

END Class.
Что обычно требуется от интерфейса:
- чтобы можно было включать объект (Object) в список разнородных объектов (не обязательно унаследованных от одного общего предка), по признаку поддержки интерфейса (Writer);
- чтобы при компиляции выдавалась ошибка, если не все методы интерфейса реализованы.

Первое возможно благодаря опубликованному полю writer. Можно создать массив или список объектов типа Interface.Writer, при этом скрытые поля this будут указывать на реальные объекты произвольных типов, с которыми далее можно вести работу через методы интерфейса - например, в цикле вызвать для всех сохранение в файл.
Второе тоже поддерживается, так как КП требует реализации всех абстрактных унаследованных методов при объявлении не-абстрактного наследника.

Отличие от Java также заключается в том, что для каждого экземпляра объекта Object мы вынуждены создавать экземпляры ObjectWriter для всех поддерживаемых интерфейсов. Ведь у нас роль интерфейса берёт на себя отдельный самостоятельный объект. Насколько я знаю, в Java все проверки интерфейсов проводятся во время компиляции, и во время исполнения везде используется ссылка на сам объект Object, без дополнительной нагрузки на динамическую память для создания посредников. Как вариант, вместо поля writer можно использовать методы типа GetWriter(): Interface.Writer, и создавать экземпляры ObjectWriter только когда и если они потребуются.

Ещё интерфейсы используются для маркировки объектов. Заводится пустой интерфейс (без методов и полей) с говорящим названием, например, Serializable, и во время выполнения система ищет объекты, реализующие такой интерфейс, и воспринимает это как знак того, что с объектом нужно сделать что-то особенное (например, сохранить его поля в БД при выгрузке программы). В ББ это тоже можно сделать средствами модуля Meta, при этом, наверное, не нужно даже создавать экземпляр интерфейсного объекта, достаточно объявить поле соответствующего типа.

PS: можно в Вики.
UPD: Вспомнил про абстрактные методы и заменил в определении метода Interface.Writer.Write ключевое слово EMPTY на ABSTRACT.

Автор:  Валерий Лаптев [ Понедельник, 31 Октябрь, 2011 12:43 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

0. Спасибо!
1. В Вики - обязательно!
2. Именно это я и предполагал. Получается, моделируем множественность интерфейсов с помощью модулей - на счет раз! Отлично!

Автор:  Сергей Губанов [ Понедельник, 31 Октябрь, 2011 13:12 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Александр Ильин писал(а):
КП не требует реализации всех пустых унаследованных методов абстрактного класса. Вместо этого получим ошибку времени выполнения при попытке вызова EMPTY-метода (насколько я знаю).
Не так, её тушка-пустышка сгенерится автоматом (синтаксический сахар). Вызывай её сколько хочешь.
Валерий Лаптев писал(а):
Получается, моделируем множественность интерфейсов с помощью модулей
Модули тут не при чём.

Автор:  Madzi [ Понедельник, 31 Октябрь, 2011 13:15 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

А можно пример для объекта, который наследуется от другого объекта и реализует три интерфейса?
Типа:
Код:
class MyData extends SomeData implements Observable, Drawable, Serializable {
...
}

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

Автор:  Евгений Темиргалеев [ Понедельник, 31 Октябрь, 2011 13:18 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Александр Ильин писал(а):
Второе не поддерживается, так как КП не требует реализации всех пустых унаследованных методов абстрактного класса. Вместо этого получим ошибку времени выполнения при попытке вызова EMPTY-метода (насколько я знаю).
Language Report писал(а):
10.2 Methods
...
Abstract methods are never called... Calling an empty method has no effect.

Автор:  Сергей Губанов [ Понедельник, 31 Октябрь, 2011 13:31 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Madzi писал(а):
Вся идея интерфейсов в том, что это контракт объекта с системой на обязательную реализацию определённых методов, и система проверяет этот контракт на этапе компиляции.
Вот пожалуйста:
Код:
TYPE
  ObserDrawSeri = POINTER TO ABSTRACT RECORD
    PROCEDURE (x: ObserDrawSeri) as_Observable(): Observable, NEW, ABSTRACT;
    PROCEDURE (x: ObserDrawSeri) as_Drawable(): Drawable, NEW, ABSTRACT;
    PROCEDURE (x: ObserDrawSeri) as_Serializable(): Serializable, NEW, ABSTRACT;
  END;

  MyData = POINTER TO RECORD (ObserDrawSeri)
    ...
  END

Автор:  Александр Ильин [ Понедельник, 31 Октябрь, 2011 13:44 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Madzi писал(а):
Вся идея интерфейсов в том, что это контракт объекта с системой на обязательную реализацию определённых методов, и система проверяет этот контракт на этапе компиляции. В вашем случае - контракт не проверяется, а нарушается по факту (т.е. контракта нет). Т.е. это не совсем интерфейс в идеологическом смысле. Контракты вещь архиполезная, особенно для доказательного программирования.
Если мы ведём речь о том, что EMPTY-методы не отсигналятся как нереализованные на этапе компиляции, то в моём случае скорее есть пустая реализация интерфейса. Хорошо это или плохо - вопрос отельный и зависит от потребностей системы и смысла самого интерфейса. Факт, однако, заключается в том, что в Яве и других языках тоже можно сделать пустую реализацию, успешно пройти компиляцию и, в результате, не соблюдать контракт. В полном смысле проверить соблюдение контракта не возможно. Единственное отличие моего примера от поведения Явы - отсутствие сообщения компилятора "не реализован метод <MethodName>".

В этом месте я прошу прощения. Я забыл, что процедуры в КП тоже можно пометить как ABSTRACT, и тогда компилятор всё-таки требует их реализации, поимённо, как только мы объявляем унаследованную не-ABSTRACT запись. Поправил исходное сообщение.
Madzi писал(а):
А можно пример для объекта, который наследуется от другого объекта и реализует три интерфейса?
Типа:
Код:
class MyData extends SomeData implements Observable, Drawable, Serializable {
...
}
Конечно:
Код:
TYPE MyData = POINTER TO RECORD (SomeData)
   PROCEDURE AsObservable* (): Observable.Interface;
   PROCEDURE AsDrawable* (): Drawable.Interface;
   PROCEDURE AsSerializable* (): Serializable.Interface;
   ...
END;

Автор:  Илья Ермаков [ Понедельник, 31 Октябрь, 2011 14:18 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Да, композиция позволяет что угодно.
Если какая-то система выступает в двух ролях, то значит, в ней есть подсистемы, ответственные за эти роли. Делим на части.

Вообще, наличие у класса больше 6-7 методов (не считая банальных Get-Set) позволительно только для классов очень широкого применения. А уж больше 10 (как правило) - признак нездорового проектирования. Когда недоделана декомпозиция.

Автор:  kemiisto [ Вторник, 01 Ноябрь, 2011 00:00 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Подробности озвученного подхода от, так сказать, отцов-основателей тут. :wink:

Автор:  Валерий Лаптев [ Вторник, 01 Ноябрь, 2011 06:52 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Илья Ермаков писал(а):
Да, композиция позволяет что угодно.
Если какая-то система выступает в двух ролях, то значит, в ней есть подсистемы, ответственные за эти роли. Делим на части.

Вообще, наличие у класса больше 6-7 методов (не считая банальных Get-Set) позволительно только для классов очень широкого применения. А уж больше 10 (как правило) - признак нездорового проектирования. Когда недоделана декомпозиция.

1. При использовании композиции вместо наследования не выполняется принцип подстановки.
2. Когда "стряпается" новый тип данных, то операций бывает довольно много. Вон деньги: почти все операции, кроме умножения.

Автор:  Валерий Лаптев [ Вторник, 01 Ноябрь, 2011 06:54 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

kemiisto писал(а):
Подробности озвученного подхода от, так сказать, отцов-основателей тут. :wink:

Спасибо! Почитаем.

Автор:  Info21 [ Вторник, 01 Ноябрь, 2011 07:30 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Валерий Лаптев писал(а):
Илья Ермаков писал(а):
Да, композиция позволяет что угодно. ...
1. При использовании композиции вместо наследования не выполняется принцип подстановки.
Надо различать
-- наследование интерфейса (что подразумевает И.Е.), где с принципом подстановки всё в порядке;
-- наследование реализации -- именно вместо него композиция.

Автор:  Сергей Губанов [ Вторник, 01 Ноябрь, 2011 13:14 ]
Заголовок сообщения:  Re: Моделирование интерфейсов

Валерий Лаптев писал(а):
не выполняется принцип подстановки
Подставляйте y.as_X() в процедуру требующую X.

Объявление: PROCEDURE F(x: X);

Вызов: F(y.as_X())

Здесь y: Y и
Код:
TYPE
  Y = POINTER TO RECORD
    PROCEDURE (y: Y) as_X (): X, NEW;
  END

Страница 1 из 6 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/