OberonCore
https://forum.oberoncore.ru/

Пример использования абстрактных типов с Meta
https://forum.oberoncore.ru/viewtopic.php?f=35&t=3005
Страница 1 из 1

Автор:  Иван Денисов [ Четверг, 18 Ноябрь, 2010 16:23 ]
Заголовок сообщения:  Пример использования абстрактных типов с Meta

При разборе пакета SQL наконец внятно понял, зачем нужны абстрактные типы и Meta :)

Родился один пример, чтобы проверить, как такое безобразие уживается в dll. Подумал, что это может оказаться полезным тем, кто хочет разобраться с использованием абстрактных типов.

Вначале мы абстрактно описываем некоторый процесс, например есть объект содержащий вектор, есть функция вычисления длины. Вот и все. А реализовать это можно разными способами и реализации легко менять в BB. Объект не зря называется Driver, поскольку такой подход удобен в случае, например, общения с базой данных.
Код:
MODULE MyDriver;
   IMPORT Meta;
   TYPE
      Driver* = POINTER TO ABSTRACT RECORD
         x*, y*: REAL;
      END;
      Realisation = PROCEDURE (OUT d: Driver);

   PROCEDURE (d: Driver) Len* (): REAL, NEW, ABSTRACT;
   PROCEDURE (d: Driver) Values* (x, y: REAL), NEW, ABSTRACT;
   
   PROCEDURE Load* (realisation: ARRAY OF CHAR; OUT d: Driver; OUT res: INTEGER);
      VAR item: Meta.Item; mod: Meta.Name; ok, a: BOOLEAN; t: INTEGER;
         v: RECORD (Meta.Value)
            Load: Realisation
         END;
   BEGIN
      mod := realisation$;
      Meta.Lookup(mod, item); d := NIL; res := 0;
      IF item.obj = Meta.modObj THEN
         item.Lookup("Load", item);
         IF item.obj = Meta.procObj THEN
            item.GetVal(v, ok);
            IF ok THEN
               v.Load(d);
               res := 0
            ELSE
               res := 3
            END
         ELSE
            res := 2
         END
      ELSE
         res := 1
      END
   END Load;

END MyDriver.


Затем описываем первую реализацию драйвера.
Код:
MODULE MyRealisation;
   IMPORT Math, MyDriver;
   TYPE
      Driver = POINTER TO RECORD (MyDriver.Driver) END;

   PROCEDURE (d: Driver) Len* (): REAL;
   BEGIN
      RETURN Math.Sqrt(Math.IntPower(d.x, 2) + Math.IntPower(d.y, 2))
   END Len;

   PROCEDURE (d: Driver) Values* (x, y: REAL);
   BEGIN
      d.x := x;
      d.y := y;
   END Values;
   
   PROCEDURE Load* (OUT d: MyDriver.Driver);
      VAR i: INTEGER; h: Driver;
   BEGIN
      NEW(h); d := h;
   END Load;

END MyRealisation.


И вторую реализацию.
Код:
MODULE MyRealisation2;

   IMPORT Math, MyDriver;

   TYPE
      Driver = POINTER TO RECORD (MyDriver.Driver) END;

   PROCEDURE (d: Driver) Len* (): REAL;
   BEGIN
      RETURN Math.Sqrt(d.x*d.x + d.y*d.y)
   END Len;
   
   PROCEDURE (d: Driver) Values* (x, y :REAL);
   BEGIN
      d.x := x;
      d.y := y;
   END Values;

   PROCEDURE Load*(OUT d: MyDriver.Driver);
      VAR i: INTEGER; h: Driver;
   BEGIN
      NEW(h); d := h;
   END Load;

END MyRealisation2.


Ну и наконец — использование.
Код:
MODULE MyUsage;

   IMPORT MyDriver, Out:=StdLog;

   PROCEDURE Test*();
      VAR d1, d2: MyDriver.Driver; res1, res2: INTEGER;
   BEGIN
      MyDriver.Load("MyRealisation", d1, res1);
      MyDriver.Load("MyRealisation2", d2, res2);
      IF (res1 = 0) & (res2 = 0) THEN
         d1.Values(12, 10);
         d2.Values(12, 10);
         Out.Real(d1.Len() + d2.Len())
      ELSE
         Out.String("Error")
      END
   END test;

END MyUsage.


Я все это делал, чтобы проверить, как такая функция будет работать в dll и что указывать при компиляции библиотеки, получается надо просто указывать обе реализации. Вроде работает.

Если вместо Out сделать RETURN.
^Q DevLinker.LinkDll
test.dll := Kernel+ Math Meta MyDriver MyRealisation MyRealisation2 MyUsage # ~

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