Оберон-клуб «ВЄДАsoft» https://zx.oberon.org/forum/ |
|
Модуль Stores https://zx.oberon.org/forum/viewtopic.php?f=79&t=390 |
Страница 1 из 2 |
Автор: | Len [ 19 июн 2018, 16:44 ] |
Заголовок сообщения: | Модуль Stores |
В модуле ObxStores я встретил незнакомые мне конструкции (выделено красным): IMPORT Dialog, Files, Stores; TYPE Node = POINTER TO RECORD (Stores.Store) a, b: Node END; (* Methods of Node *) PROCEDURE (n: Node) Externalize (VAR w: Stores.Writer); BEGIN w.WriteStore(n.a); w.WriteStore(n.b) END Externalize; PROCEDURE (n: Node) Internalize (VAR r: Stores.Reader); VAR s: Stores.Store; BEGIN r.ReadStore(s); IF (s # NIL) & (s IS Node) THEN n.a := s(Node) ELSE n.a := NIL END; r.ReadStore(s); IF (s # NIL) & (s IS Node) THEN n.b := s(Node) ELSE n.b := NIL END END Internalize; PROCEDURE (n: Node) CopyFrom (source: Stores.Store); BEGIN WITH source: Node DO IF source.a # NIL THEN n.a := Stores.CopyOf(source.a)(Node) ELSE n.b := NIL END; IF source.b # NIL THEN n.b := Stores.CopyOf(source.b)(Node) ELSE n.b := NIL END END END CopyFrom; PROCEDURE NewGraph (): Node; VAR n: Node; BEGIN NEW(n); NEW(n.a); Stores.Join(n, n.a); NEW(n.b); Stores.Join(n, n.b); n.a.a := n.b; n.a.b := NIL; n.b.a := n.a; n.b.b := n.b; RETURN n END NewGraph; PROCEDURE GraphOk (n: Node): BOOLEAN; BEGIN RETURN (n # n.a) & (n # n.b) & (n.a # n.b) & (n.a.a = n.b) & (n.a.b = NIL) & (n.b.a = n.a) & (n.b.b = n.b) & Stores.Joined(n, n.a) & Stores.Joined(n, n.b) END GraphOk; (* Demonstrate Ex- and Internalization *) PROCEDURE WriteRead*; VAR n, m: Node; f: Files.File; w: Stores.Writer; r: Stores.Reader; s: Stores.Store; BEGIN (* allocate and check new graph *) n := NewGraph(); ASSERT(GraphOk(n), 1); (* externalize graph to a temporary file *) f := Files.dir.Temp(); w.ConnectTo(f); w.WriteStore(n); (* read graph back from file *) r.ConnectTo(f); r.ReadStore(s); m := s(Node); (* check graph to be internalized with nodes correctly linked and joined *) ASSERT(GraphOk(m), 2); Dialog.ShowMsg("WriteRead test ok.") END WriteRead; Что даёт в типе запись объявление (Stores.Store) после слова RECORD? Что за странный вызов метода: s(Node), ведь в модуле Store под s сразу несколько методов: Код: "OBERON"
|
Автор: | geniepro [ 20 июн 2018, 06:10 ] |
Заголовок сообщения: | Re: Модуль Stores |
Len писал(а): В модуле ObxStores я встретил незнакомые мне конструкции (выделено красным): TYPE Node = POINTER TO RECORD (Stores.Store) r.ConnectTo(f); r.ReadStore(s); m := s(Node); Что даёт в типе запись объявление (Stores.Store) после слова RECORD? Что за странный вызов метода: s(Node) Это же основы ООП оберонов. Node = POINTER TO RECORD (Stores.Store) значит, что запись Node является указателем на запись, которая является расширением записи Store из модуля Stores. s(Node) в данном случае является преобразованием переменной s типа Store к типу Node, в сишных языках это записывается как (Node)s, Вирт же решил сделать не как в сях, а так, что бы можно было легко спутать с вызовом процедуры. Ну, скажем, в Аде тоже есть неоднозначность в такой записи -- то ли это вызов функции, то ли обращение к элементу массива... |
Автор: | Len [ 22 июн 2018, 16:12 ] |
Заголовок сообщения: | Re: Модуль Stores |
geniepro писал(а): s(Node) в данном случае является преобразованием переменной s типа Store к типу Node Зачем вообще преобразовывать переменную s типа Store к типу Node, не проще ли было сразу объявить её как Node? |
Автор: | Zorko [ 22 июн 2018, 20:01 ] |
Заголовок сообщения: | Re: Модуль Stores |
Там же иерархия типов. Потомок может сойти за родителя, т.к. обладает всеми его свойствами. Является, так сказать, родителем плюс. Бывает так, что объявлен указатель типа родитель, а ему присваивают ссылку на потомка. Вот в этом случае и преобразовывают. С Node и Store так же. Дочь является потомком ПапаМама и ссылка на неё может храниться в указателе типа ПапаМама. Обращение к её индивидуальным полям в этом случае происходит так: Код: "OBERON"
Это безопасное "преобразование", правильность соответствия таких типов и существования нужных полей проверяет компилятор на этапе компиляции или рантайм в момент работы программы. |
Автор: | geniepro [ 23 июн 2018, 08:36 ] |
Заголовок сообщения: | Re: Модуль Stores |
Zorko писал(а): Это безопасное "преобразование", правильность соответствия таких типов и существования нужных полей проверяет компилятор на этапе компиляции или рантайм в момент работы программы. Вообще-то тут желательно перед преобразованием сделать проверку, действительно ли в переменной типа POINTER TO ПапаМама находится адрес значения типа Дочь, иначе в рантайме может произойти ошибка. |
Автор: | geniepro [ 23 июн 2018, 09:02 ] |
Заголовок сообщения: | Re: Модуль Stores |
Len писал(а): geniepro писал(а): s(Node) в данном случае является преобразованием переменной s типа Store к типу Node Зачем вообще преобразовывать переменную s типа Store к типу Node, не проще ли было сразу объявить её как Node? В ООП это нужно для абстракции алгоритмов. Конечно, можно для каждого типа сделать одинаковый код, делающий что-то. Но если эти типы в чём-то схожи, их можно выстроить в иерархию и обобщить некоторый код. Есть и другие способы сделать подобное. Например, использовать не полиморфизм наследования, чью теорию в 70-х гг. построила Барбара Лисков, но и использовать параметрический полиморфизм родом из тех же 70-х. Вирт решил идти по пути ООП... |
Автор: | Сергей Оборотов [ 23 июн 2018, 17:09 ] |
Заголовок сообщения: | Re: Модуль Stores |
Len писал(а): сразу объявить её как Node? В r.ReadStore(s) нужен параметр типа Stores.Store, поэтому решили так сделать. |
Автор: | Len [ 25 июн 2018, 14:43 ] |
Заголовок сообщения: | Re: Модуль Stores |
Ещё вопросик: когда вызывается метод Externalize? Internalize вызывается автоматически при вызове метода ReadStore, но этот метод вызывается в самом методе Internalize, почему не получается бесконечное зацикливание? |
Автор: | Сергей Оборотов [ 26 июн 2018, 15:38 ] |
Заголовок сообщения: | Re: Модуль Stores |
Externalize соответственно вызывается когда WriteStore исполняется. Переполнения стека нет, поскольку обычно число вложенных Store ограничено. |
Автор: | Zorko [ 27 июн 2018, 05:00 ] |
Заголовок сообщения: | Re: Модуль Stores |
Иван Денисов писал(а): Если Externalize реализован для Views.View, то он вызывается при сохранении отображения. В общем случае Externalize вызывается при записи объекта Stores.Store или его наследников с помощью процедуры WriteStore.
Как ответил Сергей, получается, что там идет чтение вложенных хранилищ (Stores.Store), и их число ограничено. Хранилище (Stores.Store) может иметь в своем составе несколько дочерних объектов типа хранилища или их наследников. Вот и получается, что для их чтения необходим рекурсивный вызов. |
Страница 1 из 2 | Часовой пояс: UTC + 2 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |