Брайан прав насчет замещения Лискова (изменено). И Рид прав насчет «есть-а» (также измененный); на самом деле они оба говорят вам одно и то же.
Ваши публичные методы - это контракт с пользователями вашего класса Foo, который говорит, что "вы всегда можете" вызывать эти методы в Foo.
Подкласс Foo означает, что вы говорите, что подкласс, например Бар, всегда допустимо использовать там, где можно использовать Foo. В частности, это означает, что вы не наследуете (необязательно) реализацию Foo (вы можете переопределить это, или Foo может быть абстрактным и не давать конкретной реализации для метода).
Наследование реализации (если есть) является деталью; То, что вы действительно наследуете , - это общедоступный интерфейс, контракт, обещание пользователям, что Bar может использоваться как Foo.
Действительно, они могут даже не знать, что у них есть Bar, а не Foo: если я создаю FooFactory и пишу его Foo * getAFoo (), чтобы вернуть указатель на Bar, они могут никогда не узнать, и не должен .
Когда вы нарушаете этот контракт, вы нарушаете Ориентацию на объект. (А классы Java Collection, создавая исключения NotSupported, полностью разрушают OO - пользователи больше не могут полиморфно использовать так называемые подклассы. Это плохой, плохой дизайн, который вызвал серьезные головные боли для многих многих пользователей Java, не что-то подражать.)
Если есть открытый метод, который подклассы Foo не могут использовать, то этот метод не должен быть в Foo, он должен быть в подклассе Foo, а другие подклассы должны быть производными от Foo.
Теперь, это НЕ означает, что все методы в Foo должны вызываться на подклассах. Нет, я не противоречу себе. Непубличные методы не являются частью открытого интерфейса класса.
Если вы хотите, чтобы метод в Foo не вызывался на Bar, и не должны быть публично доступны в Foo, тогда сделайте этот метод закрытым или защищенным.