Следующая версия
|
Предыдущая версия
Следующая версия
Следующая версия справа и слева
|
bb:redbook:210 [2016/03/31 15:30] prospero78 создано |
bb:redbook:210 [2019/07/24 10:20] caufman [4. Ограниченные типы] |
==== 2. Абстрактные типы ==== | ==== 2. Абстрактные типы ==== |
Абстрактные типы не могут иметь экземпляров. Казалось бы, парадокс: зачем нужно создавать типы данных, которые нельзя использовать? Оказывается, в этом есть смысл, если потом, на базе такого типа, будут создаваться другие типы, которые реализуют абстрактный тип. Они все будут разные, но поскольку в основе их лежит один базовый тип, те операции, которые определены для базового типа, вполне успешно могут быть использованы и в типах-потомках. Пример с неправильным использованием абстрактного типа приведён ниже: | Абстрактные типы не могут иметь экземпляров. Казалось бы, парадокс: зачем нужно создавать типы данных, которые нельзя использовать? Оказывается, в этом есть смысл, если потом, на базе такого типа, будут создаваться другие типы, которые реализуют абстрактный тип. Они все будут разные, но поскольку в основе их лежит один базовый тип, те операции, которые определены для базового типа, вполне успешно могут быть использованы и в типах-потомках. Пример с неправильным использованием абстрактного типа приведён ниже: |
| MODULE Test_abstract; |
| |
| TYPE |
| tVector = ABSTRACT RECORD |
| x: REAL; |
| y: REAL; |
| END; |
| |
| VAR |
| v: tVector; |
| |
| BEGIN |
| END Test_abstract. |
Компилятор прозрачно намекает, что так делать нельзя. Исправленный пример приводится ниже: | Компилятор прозрачно намекает, что так делать нельзя. Исправленный пример приводится ниже: |
| MODULE Test_abstract; |
| |
| TYPE |
| tVector = ABSTRACT RECORD |
| x: REAL; |
| y: REAL; |
| END; |
| |
| tMyVector1 = RECORD (tVector) |
| z: REAL; |
| END; |
| |
| tMyVector2 = RECORD (tVector) |
| v: REAL; |
| END; |
| |
| VAR |
| v: tMyVector1; |
| v1: tMyVector2; |
| |
| BEGIN |
| END Test_abstract. |
Как видно из примера, вслед за типом tVector определяется тип-потомок tMyVector1, который в качестве базового использует абстрактный тип tVector. И такой тип уже не является абстрактным. В типе tMyVector1 добавляется поле z, которого нет в базовом типе. А в его родственнике по базовому типу, добавляется поле v, того же типа, что и z, но эти два типа уже обладают разным поведением, и это разные типы, хотя действия, определённые для базового типа tVector к ним обоим успешно применимы (в приведённом примере у базового типа методы не описаны). | Как видно из примера, вслед за типом tVector определяется тип-потомок tMyVector1, который в качестве базового использует абстрактный тип tVector. И такой тип уже не является абстрактным. В типе tMyVector1 добавляется поле z, которого нет в базовом типе. А в его родственнике по базовому типу, добавляется поле v, того же типа, что и z, но эти два типа уже обладают разным поведением, и это разные типы, хотя действия, определённые для базового типа tVector к ним обоим успешно применимы (в приведённом примере у базового типа методы не описаны). |
| |
==== 3. Расширяемые типы ==== | ==== 3. Расширяемые типы ==== |
Расширяемые типы чем-то похожи на абстрактные. Отличие состоит в том, что тип, описанный как расширяемый, может быть использован сразу: без необходимости наследовать его, прежде чем, создать экземпляр типа. Пример использования представлен ниже: | Расширяемые типы чем-то похожи на абстрактные. Отличие состоит в том, что тип, описанный как расширяемый, может быть использован сразу: без необходимости наследовать его, прежде чем, создать экземпляр типа. Пример использования представлен ниже: |
| MODULE Test_extensible; |
| |
| TYPE |
| tVector = EXTENSIBLE RECORD |
| x: REAL; |
| y: REAL; |
| END; |
| |
| tMyVector1 = RECORD (tVector) |
| z: REAL; |
| END; |
| |
| VAR |
| v: tVector; |
| v1: tMyVector1; |
| |
| BEGIN |
| END Test_extensible. |
Абстрактный тип, также может расширяться в типах-потомках, но не может быть реализован. Далеко не всегда в качестве базового типа необохдимо использовать абстрактный тип. Да и гораздо чаще возникает необходимость расширить существующий тип, чем создавать тип с чистого листа. Стоить отметить, что раз введено такое семантическое свойство, как "расширяемый тип", очевидно, что без ключевого слова EXTENSIBLE тип расширить нельзя. Это поведение типа по умолчанию (как и сокрытие данных). [↑] | Абстрактный тип, также может расширяться в типах-потомках, но не может быть реализован. Далеко не всегда в качестве базового типа необохдимо использовать абстрактный тип. Да и гораздо чаще возникает необходимость расширить существующий тип, чем создавать тип с чистого листа. Стоить отметить, что раз введено такое семантическое свойство, как "расширяемый тип", очевидно, что без ключевого слова EXTENSIBLE тип расширить нельзя. Это поведение типа по умолчанию (как и сокрытие данных). [↑] |
| |
| |
Пример приводится ниже: | Пример приводится ниже: |
| MODULE Test_limited; |
| |
| TYPE |
| tVector = LIMITED RECORD |
| x: REAL; |
| y: REAL; |
| END; |
| |
| tMyVector1 = RECORD (tVector) |
| z: REAL; |
| END; |
| |
| VAR |
| v: tVector; |
| v1: tMyVector1; |
| |
| BEGIN |
| END Test_limited. |
Как видно в примере, при попытке его скомпилировать, возникла ошибка. Так как тип-потомок также должен наследовать атрибут ограничения. | Как видно в примере, при попытке его скомпилировать, возникла ошибка. Так как тип-потомок также должен наследовать атрибут ограничения. |
| |
Исправленный пример ниже: | Исправленный пример ниже: |
| MODULE Test_limited; |
| |
| TYPE |
| tVector = LIMITED RECORD |
| x: REAL; |
| y: REAL; |
| END; |
| |
| tMyVector1 = LIMITED RECORD (tVector) |
| z: REAL; |
| END; |
| |
| VAR |
| v: tVector; |
| v1: tMyVector1; |
| |
| BEGIN |
| END Test_limited. |
И как видно, никаких вопросов у компилятора к программисту не возникает. [↑] | И как видно, никаких вопросов у компилятора к программисту не возникает. [↑] |
| |