Оберон-клуб «ВЄДАsoft»
https://zx.oberon.org/forum/

Приведение типов родственных объектов
https://zx.oberon.org/forum/viewtopic.php?f=79&t=393
Страница 1 из 1

Автор:  Len [ 04 июл 2018, 06:31 ]
Заголовок сообщения:  Приведение типов родственных объектов

В модуле ObxStores в конце процедуры WriteRead есть строчка m:=s(Node). Как я понимаю, это приведение объекта предка к потомку. Я написал два модуля но приведение получается (притом неявное) только от потомка к предку (модуль Mod2 метод Start), в обратную сторону - никак. Но почему это получилось в ObxStores?
Код: "OBERON"
  1. MODULE Mod1
  2.  
  3. IMPORT StdLog;
  4.  
  5. TYPE
  6. ancestor* = POINTER TO EXTENSIBLE RECORD
  7. i*: INTEGER
  8. END;
  9.  
  10. VAR
  11. ance: ancestor;
  12.  
  13. PROCEDURE (anc: ancestor) Start*, NEW, EXTENSIBLE;(**)
  14. BEGIN
  15. StdLog.String ("Процедура предок")
  16. END Start;
  17.  
  18. END Mod1.

Код: "OBERON"
  1. MODULE Mod2
  2.  
  3. IMPORT StdLog, Mod1;
  4.  
  5. TYPE
  6. descendant = POINTER TO RECORD (Mod1.ancestor)
  7. b: BYTE
  8. END;
  9.  
  10. VAR
  11. desce: descendant;
  12.  
  13. PROCEDURE (des: descendant) Start;(**)
  14. VAR
  15. ance: Mod1.ancestor;
  16. BEGIN
  17. NEW(ance);
  18. StdLog.String ("Процедура потомок");
  19. ance := desce
  20. END Start;
  21.  
  22. BEGIN
  23. NEW(desce);
  24. desce.Start
  25. END Mod2.

Автор:  ivan_denisov [ 04 июл 2018, 08:31 ]
Заголовок сообщения:  Re: Приведение типов родственных объектов

Вот для таких случаев это надо:
Код: "OBERON"
  1. PROCEDURE (des: descendant) Start;(**)
  2. VAR
  3. ance: Mod1.ancestor;
  4. BEGIN
  5. NEW(ance);
  6. StdLog.String ("Процедура потомок");
  7. des := ance(descendant)
  8. END Start;

Автор:  Len [ 04 июл 2018, 13:13 ]
Заголовок сообщения:  Re: Приведение типов родственных объектов

ivan_denisov писал(а):
Вот для таких случаев это надо:
Код: "OBERON"
  1. PROCEDURE (des: descendant) Start;(**)
  2. VAR
  3. ance: Mod1.ancestor;
  4. BEGIN
  5. NEW(ance);
  6. StdLog.String ("Процедура потомок");
  7. des := ance(descendant)
  8. END Start;

Нет, к сожалению выдаёт ошибку во время выполнения.

Автор:  SovietPony [ 04 июл 2018, 21:38 ]
Заголовок сообщения:  Re: Приведение типов родственных объектов

Падает потому что типы не совпадают. Да и в данном случае такое приведение типа бессмысленно.
Поиграйся с такой процедуркой, внимательно посмотри на передаваемые параметры в Test:
Код: "OBERON"
  1.  
  2. PROCEDURE TypeTest (x: Mod1.ancestor);
  3. VAR y: Mod2.descendant;
  4. BEGIN
  5. IF x IS Mod2.descendant THEN
  6. StdLog.String ("Приведение типа возможно"); StdLog.Ln;
  7. y := x(Mod2.descendant);
  8. y.i := 666;
  9. y.b := 42
  10. ELSE
  11. StdLog.String ("Приведение типа невозможно"); StdLog.Ln;
  12. x.i := 1337
  13. END
  14. END TypeTest.
  15.  
  16. PROCEDURE Test*;
  17. VAR w: Mod2.descendant; q: Mod1.ancestor;
  18. BEGIN
  19. NEW(w); TypeTest(w);
  20. NEW(q); TypeTest(q);
  21. q := w; TypeTest(q)
  22. END Test;
  23.  

И вообще, почитай уже описание языка, что ли.

Автор:  geniepro [ 06 июл 2018, 11:22 ]
Заголовок сообщения:  Re: Приведение типов родственных объектов

Len писал(а):
В модуле ObxStores в конце процедуры WriteRead есть строчка m:=s(Node). Как я понимаю, это приведение объекта предка к потомку. Я написал два модуля но приведение получается (притом неявное) только от потомка к предку (модуль Mod2 метод Start), в обратную сторону - никак.

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

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

Автор:  Len [ 06 июл 2018, 15:39 ]
Заголовок сообщения:  Re: Приведение типов родственных объектов

geniepro писал(а):
И вообще, почитай уже описание языка, что ли.

Ты имеешь в виду документацию к ББ? Если её, то поясни где именно написано о приведении типов объектов.

Автор:  SovietPony [ 06 июл 2018, 17:53 ]
Заголовок сообщения:  Re: Приведение типов родственных объектов

Help -> Contents -> Language Report
Цитата:
8.1 Operands
...
A type guard v(T) asserts that the dynamic type of v is T (or an extension of T), i.e., program execution is aborted, if the dynamic type of v is not T (or an extension of T). Within the designator, v is then regarded as having the static type T. The guard is applicable, if
1. v is an IN or VAR parameter of record type or v is a pointer to a record type, and if
2. T is an extension of the static type of v
...

Автор:  Len [ 07 июл 2018, 04:48 ]
Заголовок сообщения:  Re: Приведение типов родственных объектов

Нашёл!
Цитата:
Охрана типа [type guard] v(T) удостоверяет, что динамический тип переменной v есть T (или потомок типа T), т.е. выполнение программы аварийно прекращается, если динамический тип переменной v не T (и не потомок T). Тогда внутри составного имени переменная v считается имеющей статический тип T. Охрана применима, если
1. v является IN или VAR параметром записевого типа или v является указателем на запись, и если
2. T является потомком статического типа переменной v

Благодарю.

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