Введение

Проблема системы объектно-ориентированного программирования – архитектурная проблема.

Проблема хрупкого базового класса – это фундаментальная архитектурная проблема систем объектно-ориентированного программирования, при которой базовые классы (суперклассы) считаются "хрупкими", поскольку, казалось бы, безопасные изменения в базовом классе, при наследовании производными классами, могут привести к сбоям в работе производных классов. Программист не может определить, является ли изменение базового класса безопасным, просто изучая методы базового класса изолированно. Одним из возможных решений является объявление переменных экземпляра приватными для класса, в котором они определены, и принуждение подклассов использовать методы доступа (аксессоры) для изменения состояния суперкласса. Язык программирования также может предоставить подклассам возможность контролировать, какие унаследованные методы будут доступны извне. Эти изменения предотвращают зависимость подклассов от деталей реализации суперклассов и позволяют подклассам предоставлять доступ только к тем методам суперкласса, которые им необходимы. Альтернативным решением является использование интерфейса вместо суперкласса. Проблема хрупкого базового класса связывается с открытой рекурсией (динамической диспетчеризацией методов через `this`), с предложением, что вызов методов через `this` по умолчанию должен использовать закрытую рекурсию (статическую диспетчеризацию, раннее связывание), а не открытую рекурсию (динамическую диспетчеризацию, позднее связывание), применяя открытую рекурсию только при явном запросе; внешние вызовы (не использующие `this`) должны осуществляться с динамической диспетчеризацией, как обычно.

Решение

Objective C имеет категории и нехрупкие переменные экземпляра. Component Pascal отказывается от вызовов суперкласса. Java, C++ (начиная с C++11) и D позволяют запретить наследование или переопределение метода класса, помечая объявление класса или метода соответственно ключевым словом "final". В книге Effective Java автор Джошуа Блох пишет (в пункте 17), что программисты должны "проектировать с учетом наследования или же явно его запрещать". C# и VB.NET, как и Java, имеют ключевые слова "sealed" и "Not Inheritable" для объявления класса с целью запрета наследования, и требуют, чтобы подкласс использовал ключевое слово "override" при переопределении методов – то же решение, позже принятое Scala. Scala требует, чтобы подкласс явно использовал ключевое слово "override" для переопределения метода родительского класса. В книге "Программирование на Scala, 2-е издание" автор пишет (с некоторыми изменениями), что если бы метода f не существовало, исходная реализация метода f в клиентском коде не могла бы иметь модификатор переопределения. После добавления метода f во вторую версию класса библиотеки повторная компиляция клиентского кода приведет к ошибке компиляции, а не к неправильному поведению. В Kotlin классы и методы по умолчанию являются финальными. Чтобы разрешить наследование класса, класс должен быть помечен модификатором "open". Аналогично, метод должен быть помечен как "open", чтобы разрешить его переопределение. Julia допускает только подтипирование абстрактных типов и использует композицию как альтернативу наследованию, однако поддерживает множественную диспетчеризацию.