Динамическое связывание сообщений с методами
Заметим, что список динамически связываемых методов, вызываемых из объектов, одинаков для всех экземпляров конкретного класса. Таким образом, список таких методов можно хранить только в одном месте. Отсюда вывод: в структуре СЭК объекта следует иметь только один указатель на список, обеспечивающий нахождение вызываемых методов. Структуру памяти для хранения этого списка обычно называют таблицей виртуальных методов ТВМ.
Адрес нужного метода находится по конкретному смещению от начала таблицы ТВМ. Полиморфные переменные родительского класса всегда ссылаются на структуру СЭК объекта нужного типа, поэтому получение нужной версии динамически связываемого метода гарантируется. Рассмотрим фрагмент на языке Java, в котором все методы предполагаются динамически связываемыми:
Реализация объектно-ориентированных классов и объектов |
501 |
public class Child extends Parent { public int m, n; public void display() { . . . } public void move() { . . . } } Структуры СЭК для классов Parent и Child, а также таблицы их виртуальных методов представлены на рис. 16.24. Заметим, что указатель на метод square() из таблицы для Child указывает на реализацию в классе Parent. Причина в том, что класс Child не переопределяет этот родительский метод, поэтому, когда клиент Child будет вызывать square(), реализация данного метода берется из Parent. С другой стороны, указатели на display() и move() из виртуальной таблицы для Child указывают на их реализации из Child. Метод display() переопределен в Child, а move() просто добавлен. |
Рис. 16.24. Структуры СЭК и таблицы виртуальных методов для классов Parent и Child |
Множественное наследование усложняет реализацию динамического связыва- ния. Рассмотрим следующие определения классов на языке C++: |
продолжение # |
502 Глава 16. Объектно-ориентированное и аспектно-ориентированное программирование |
Классe С наследует переменную а и метод орА2() из класса А. Он переопределяет метод орА1(), хотя и сам метод, и его родительская версия потенциально видимы через полиморфную переменную (типа А). От класса В класс С наследует переменную Ь и метод орВ(). Кроме того, класс С определяет свою собственную переменную с и добавляет не унаследованный метод орС(). Структура СЭК для С должна содержать данные классов А, В и С, а также средства для доступа ко всем видимым методам. При единичном наследовании СЭК содержит указатель на виртуальную таблицу, которая адресует реализации всех видимых методов. При множественном наследовании все не так просто. В СЭК должны отражаться два представления: по одному для каждого родительского класса, причем в одно из них нужно включить представление для подкласса С. Подобное включение представления подкласса в представление родительского класса должно быть эквивалентно реализации единичного наследования. Необходимы две виртуальные таблицы: одна для представления классов А и С, другая — для представления класса В. В этом случае первая часть СЭК для класса С содержит представление классов С и А со следующей структурой: 1) указатель виртуальной таблицы для методов С и тех методов, которые унаследованы от А; 2) данные, унаследованные от А. |
Рис. 16.25. Пример СЭК для подкласса с двумя родителями |
Вторая часть в СЭК для класса С должна представлять класс В. Эта часть имеет следующую структуру: |
Особенности аспектно-ориентированного подхода |
503 |
1) указатель виртуальной таблицы для виртуальных методов В; 2) данные, унаследованные от В; 3) данные, определенные в С. Структура СЭК для класса С показана на рис. 16.25. |