СТРУКТУРЫ И ПОРОЖДАЕМЫЕ ТИПЫ |
Структуры в Caper 4 определяются посредством следующей определяющей формы: struct <имя структуры> { <описатель члена структуры> <имя структуры> ::= <идентификатор> Так, в приведенном ниже примере Пример: struct ListValue { <word> point1, => struct tagStru { => элемент структуры tagStru с номером 1 (см. нумерацию в комментариях) является переменной простого типа (build не имеет смысла). Элемент с номером 2 фактически
развертывается в три члена структуры <ListValue>. Здесь бессмысленны оба атрибута (и build, и ref). Все остальные элементы структуры (3-6) являются составными и могут иметь оба возможных атрибута, что и продемонстрировано.
Так, при генерации тела структуры в нем будут размещены тела массива 3 и структуры 6, в то время как под myFuncs и otherFuncs (элементы 4,5) будут выделены места как для обычных переменных, которые будут хранить указания на
массивы структур.
Операция указания элемента структуры определяется символом ‘.’ (точка). После определения переменной структуры возможны stru1.iVar := 10 Однако stru1.myFuncs[1] := user_block приведет к ошибке выполнения: массив myFuncs не создан, в то время как элемент структуры предназначен для хранения ссылки на массив. stru1.list.point1 := 30 будет выполнен корректно: тело структуры ListValue будет встроено в tagStru и определено при построении. Использование implant на первой позиции в определении структуры позволяет выравнивать новую определяемую структуру к определяющей: struct tagStru1{ <int> var1, <byte> var2 } stru1 := stru2 ;* корректное присвоение однако: породит сообщение компилятора об ошибке.К порожденным типам относятся и известные по Caper 3 коллекции. Коллекции являются совокупностями бестиповых переменных. collection <имя коллекции> { <переменная коллекции> <имя коллекции> ::= <идентификатор> Пример: collection tagColl { variable1, => private <tagColl> coll_1, <tagColl> coll_2, <string> str, <int> ii := 0 . . . coll_1.”variable1” := “ABC” str := “variable2” coll_1.1 := “CDE” ;* указание члена коллекции порядковым номером Если номер указания элемента превышает количество элементов или меньше 1, то это вызовет ошибку в процессе исполнения программы. То же, если будет указано несуществующее имя элемента коллекции.
Коллекции в программных модулях сопровождаются своими описателями. collection tagColl_1 { num1, => collection tagColl_2 { string1, => private < tagColl_1> coll_1, < tagColl_2> coll_2, <int> test Динамически созданные коллекции могут быть удалены функцией DelCollection( <указание коллекции> ) или оператором delete (см. ниже). Возвращаясь к операторной интерпретации описателя типа отметим, что memnum типа корректен только для порожденных типов и определяет количество элементов структуры: var := <memnum ListValue> * 2 ;* удвоенное количество элементов структуры ;* равно 6-ти. var := <memnum tagColl_2> ;* var == 3 В Caper 4 особое значение уделено возможностям конструирования данных порожденных типов. Так, расширены возможности задания конструкторов и деструкторов (помимо вышеопределенной формы): <конструктор> ::= .<идентификатор> Данная форма может быть использована только в комплексе с инструкциями #use module <имя модуля> предворяющими описание структур. Завершение действия #use наступает по #nouse или при встрече новой инструкции #use.Заданные конструкторы и деструкторы являются
членами структуры (если блок возвращает структуру) или коллекции (если блок возвращает коллекцию);
Конструкторы и деструкторы могут быть смешанного типа: конструктор образован согласно #use, в то время как деструктор указывать на обычный блок или вовсе отсутствовать, и наоборот. Примеры: #use module sbWindow.obc struct Window { => #nouse build private <Window> myWindow( 10, 20, 100, 200 ) Здесь по buld будет
Фактически, будет реализовано: В то время как delete myWindow приведет к import sbWindow.obc as sbWindow #use module sbWindow.obc struct Window { . . . } { .create, .delete } #nouse приведет к Использование блока выглядит следующим образом: struct WinMethods{ <block> create, => internal <WinMethods> WinLoader #use block WinLoader struct Window { . . . } { .create, .delete } #avoid Отметим еще раз, что WinLoader в данном случае должен быть определен программистом. Всякий раз, когда будет строится экземпляр структуры/коллекции build private <Window> myWindow( 10, 20, 100, 200 ) будет выполняться WinLoader().create( 10, 20, 100, 200 ) Для удаления объекта: WinLoader().delete() Далее, private <WinMethodsl> winMeth #use struct winMeth Тогда всякое построение типа build private <Window> myWin( 10, 20, 200, 300 ) winMeth.create( 10, 20, 200, 300 ) Аналогично и для коллекций: private <WinMethodsColl> winMeth #use struct winMeth И тогда - winMeth.”create( 10, 20, 200, 300 ) |