Может ли метод потомка переопределить private-метод родителя, если совпадают имя и параметры?
Нет. private-метод родителя недоступен потомку и не наследуется, поэтому одноимённый метод потомка является новым методом, а не переопределением. Аннотация @Override в такой ситуации вызовет ошибку компиляции.
Модификатор private предназначен для сокрытия деталей реализации класса. Такой метод является внутренним механизмом самого класса и не образует часть контракта, который могут изменять или реализовывать наследники.
Это поддерживает инкапсуляцию: автор класса может менять private-методы, не обещая их поведение потомкам и внешнему коду. Для расширения поведения используются методы с доступом protected или public, а также композиция.
Внешне одинаковые имя и параметры могут создать иллюзию переопределения. Из-за этого разработчик может ожидать полиморфный вызов метода потомка, хотя родительский класс продолжит обращаться к собственной private-реализации.
Такая ошибка особенно опасна в шаблонных методах: публичная операция родителя вызывает private-метод, а наследник объявляет одноимённый метод, рассчитывая изменить алгоритм. Код успешно компилируется без @Override, но поведение остаётся родительским.
Переопределение возможно только для унаследованного метода. Private-метод не наследуется, поэтому у потомка нет метода родителя, который можно было бы переопределить. Совпадение имени и параметров само по себе этого правила не меняет.
Вызов private-метода разрешается на этапе компиляции относительно класса, в котором этот метод объявлен. Поэтому вызов из метода родителя всегда обращается к реализации родителя, даже если фактический объект создан как экземпляр потомка.
Одноимённый private-метод потомка допустим: он просто существует независимо от метода родителя. Однако пометка @Override запрещена, потому что переопределения нет.
Если наследник должен изменять отдельный этап алгоритма, этот этап следует объявить, например, protected. Тогда он станет частью расширяемого контракта, а вызов через ссылку на родителя сможет использовать переопределённую реализацию потомка.
При вызове run у объекта Child будет напечатано Base. Метод Child.check не участвует в этом вызове и не переопределяет Base.check.
В базовом классе обработки документов метод process выполнял общий алгоритм и вызывал private-метод проверки. Команда добавила наследника для нового формата и объявила в нём одноимённую проверку, ожидая, что она автоматически заменит базовую.
Рассматривались варианты:
Если разные форматы действительно требуют разных проверок, обоснованным решением будет protected-точка расширения с чётко описанными предусловиями и результатом. Если проверки являются самостоятельной бизнес-логикой, предпочтительнее композиция со стратегией проверки. В обоих случаях поведение становится явным и покрывается тестами, в отличие от случайного совпадения имён private-методов.
Что произойдёт, если родительский метод вызывает private-метод, а объект фактически является экземпляром потомка?
Будет вызвана реализация private-метода родителя. Private-вызов не участвует в динамическом полиморфизме, поэтому фактический тип объекта не переключает его на одноимённый метод потомка.
Что произойдёт, если поставить @Override над одноимённым методом потомка?
Компилятор сообщит об ошибке: метод не переопределяет метод суперкласса. Аннотация @Override проверяет именно наличие допустимого переопределения, поэтому помогает обнаружить ошибочное предположение разработчика.
Может ли потомок объявить public-метод с теми же именем и параметрами, что у private-метода родителя?
Да, такой метод будет новым методом потомка, поскольку private-метод родителя не наследуется. Его более широкий модификатор доступа не означает переопределение и не создаёт полиморфной связи с методом родителя.