Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[61]

комплексные

действительные

рациональные

целые

Рис. 2.25: Башня типов

С другой стороны, могут существовать приложения, для которых наша схема приведения недостаточно обща. Даже когда ни один из объектов, которые требуется сочетать, не может быть приведен к типу другого, операция может оказаться применимой, если преобразовать оба объекта к третьему типу. Чтобы справиться с такой степенью сложности и по-прежнему сохранить модульность в наших программах, обычно необходимо строить такие системы, которые еще в большей степени используют структуру в отношениях между типами, как мы сейчас расскажем.

Иерархии типов

Описанная выше схема приведения типов опиралась на существование естественных отношений между парами типов. Часто в отношениях типов между собой существует более «глобальная» структура. Предположим, например, что мы строим обобщенную арифметическую систему, которая должна работать с целыми, рациональными, действительными и комплексными числами. В такой системе вполне естественно будет рассматривать целое число как частный случай рационального, которое в свою очередь является частным случаем действительного числа, которое опять-таки частный случай комплексного числа. Здесь мы имеем так называемую иерархию типов (hierarchy of types) в которой, например, целые числа являются подтипом (subtype) рациональных чисел (то есть всякая операция, которую можно применить к рациональному числу, применима и к целым). Соответственно, мы говорим, что рациональные числа являются надтипом (supertype) целых. Та конкретная иерархия, с которой мы имеем дело здесь, имеет очень простой вид, а именно, у каждого типа не более одного надтипа и не более одного подтипа. Такая структура, называемая башня типов (tower), показана на рис. 2.25

Если у нас имеется башня типов, то задача добавления нового типа в систему сильно упрощается, поскольку требуется указать только то, каким образом новый тип включается в ближайший надтип сверху и то, каким образом он является надтипом типа, который находится прямо под ним. Например, если мы хотим к комплексному числу добавить целое, нам не нужно специально определять процедуру приведения типа integer->complex. Вместо этого мы определяем, как можно перевести целое число в рациональное, рациональное в действительное, и как действительное число переводится в комплексное. Потом мы позволяем системе преобразовать целое число в комплексное через все эти промежуточные шаги и складываем два комплексных числа.


Можно переопределить процедуру apply-generic следующим образом: для каждого типа требуется указать процедуру raise, которая «поднимает» объекты этого типа на один уровень в башне. В таком случае, когда системе требуется обработать объекты различных типов, она может последовательно поднимать объекты более низких типов, пока все объекты не окажутся на одном и том же уровне башни. (Упражнения 2.83 и 2.84 касаются деталей реализации такой стратегии.)

Еще одно преимущество башни состоит в том, что легко реализуется представление о том, что всякий тип «наследует» операции своего надтипа. Например, если мы не даем особой процедуры для нахождения действительной части целого числа, мы все равно можем ожидать, что real-part будет для них определена в силу того, что целые числа являются подтипом комплексных. В случае башни мы можем устроить так, чтобы это происходило само собой, модифицировав apply-generic. Если требуемая операция не определена непосредственно для типа данного объекта, мы поднимаем его до надтипа и пробуем еще раз. Так мы ползем вверх по башне, преобразуя по пути свой аргумент, пока мы либо не найдем уровень, на котором требуемую операцию можно произвести, либо не доберемся до вершины (и в таком случае мы сдаемся).

Еще одно преимущество башни над иерархией более общего типа состоит в том, что она дает нам простой способ «опустить» объект данных до его простейшего представления. Например, если мы складываем 2 + 3i с 4 - 3i, было бы приятно в качестве ответа получить целое 6, а не комплексное 6 + 0i. В упражнении 2.85 обсуждается способ, которым такую понижающую операцию можно реализовать. (Сложность в том, что нам нужен общий способ отличить объекты, которые можно понизить, вроде 6 + 0i, от тех, которые понизить нельзя, например 6 + 2i.)

Неадекватность иерархий

Если типы данных в нашей системе естественным образом выстраиваются в башню, это сильно упрощает задачу работы с обобщенными операциями над различными типами, как мы только что видели. К сожалению, обычно это не так. На рисунке 2.26 показано более сложное устройство набора типов, а именно отношения между различными типами геометрических фигур. Мы видим, что в общем случае у типа может быть более одного подтипа. Например, и треугольники, и четырехугольники являются разновидностями многоугольников. В дополнение к этому, у типа может быть более одного надтипа. Например, равнобедренный прямоугольный треугольник можно рассматривать и как равнобедренный, и как прямоугольный. Вопрос с множественными надтипами особенно болезнен, поскольку из-за него теряется единый способ «поднять» тип по иерархии. Нахождение «правильного» надтипа, в котором требуется применить операцию к объекту, может потребовать долгого поиска по всей сети типов внутри процедуры вроде apply-generic. Поскольку в общем случае у типа несколько подтипов, существует подобная проблема и в сдвиге значения «вниз» по иерархии. Работа с большим количеством связанных типов без потери модульности при разработке больших систем - задача очень трудная, и в этой области сейчас ведется много исследований.52

52Данное утверждение, которое присутствует и в первом издании этой книги, сейчас столь же верно, как и двенадцать лет назад. Разработка удобного, достаточно общего способа выражать


многоугольник

трапециячетырехугольник

с перпендикулярными диагоналями

треугольник

равнобедренный прямоугольный треугольниктреугольник

ромб

равносторонний равнобедренный

треугольник тпрреяумгооулгьонлиькный квадрат

Рис. 2.26: Отношения между типами геометрических фигур.



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]