stringtranslate.com

Хрупкий базовый класс

Проблема хрупкого базового класса — это фундаментальная архитектурная проблема систем объектно-ориентированного программирования , в которых базовые классы ( суперклассы ) считаются «хрупкими», поскольку кажущиеся безопасными модификации базового класса при наследовании производными классами могут привести к сбоям в работе производных классов. . Программист не может определить, безопасно ли изменение базового класса, просто исследуя методы базового класса по отдельности.

Одним из возможных решений является сделать переменные экземпляра частными для их определяющего класса и заставить подклассы использовать методы доступа для изменения состояний суперкласса. Язык также может сделать так, чтобы подклассы могли контролировать, какие унаследованные методы будут доступны публично. Эти изменения не позволяют подклассам полагаться на детали реализации суперклассов и позволяют подклассам предоставлять только те методы суперкласса, которые применимы к ним самим.

Альтернативное решение — использовать интерфейс вместо суперкласса.

В проблеме хрупкого базового класса обвиняют открытую рекурсию (динамическую отправку методов в this), с предположением, что вызов методов по thisумолчанию для закрытой рекурсии (статическая диспетчеризация, раннее связывание), а не открытой рекурсии (динамическая диспетчеризация, позднее связывание), только использование открытой рекурсии, когда это специально запрошено; внешние вызовы (без использования this) будут динамически отправляться, как обычно. [1] [2]

Пример Java

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

класс  Супер { частный int counter = 0 ;       void Inc1 () { счетчик ++ ; }     void Inc2 () { счетчик ++ ; } }    класс  Sub расширяет Super { @Override void Inc2 () { Inc1 (); } }         

Вызов динамически связанного метода inc2() в экземпляре Sub правильно увеличит счетчик поля на единицу. Однако если код суперкласса изменить следующим образом:

класс  Супер {  частный счетчик int = 0 ;     недействительный Inc1 () { Inc2 (); }     void Inc2 () { счетчик ++ ; } }    

вызов динамически связанного метода inc2() в экземпляре Sub вызовет бесконечную рекурсию между ним и методом inc1() суперкласса и в конечном итоге вызовет переполнение стека. Этой проблемы можно было бы избежать, объявив методы суперкласса как Final , что сделало бы невозможным их переопределение подклассом. Однако это не всегда желательно и возможно. Поэтому суперклассам рекомендуется избегать изменения вызовов динамически привязанных методов.

Решения

Смотрите также

Рекомендации

  1. ^ «Выборочная открытая рекурсия: решение проблемы хрупкого базового класса», Джонатан Олдрич
  2. ^ «Выборочная открытая рекурсия: решение проблемы хрупкого базового класса», Lambda the Ultimate
  3. ^ «Модификатор переопределения — Справочник по C#» .

Внешние ссылки