Этот Ваш чудик на http://valera.ws/2007.11.11~oop_in_php пиарит .NET и делает вид, что Java не существует. Тактично не договаривая, что NET во многом калька с куда как более серъёзной технологии Java.
Надо вообще сразу писать код без ошибок и лучше на ассемблере. Причём писать так, что бы никогда потом не менять ибо в нём изначально всё было учтено. Свежая мысль. А главное - Мудрая.
А какие-такие подводные камни у этого примера? Оно ведь и понятно, что абстракция потому и абстракция, что у реальных типов будут незначительные отличия. Ставить их во главу угла (Ах!, а вы слыхали, что у квадрата ширина с длиной одинаковы, а значит это ... кашмар какой... не прямоугольник!!!). Так что никакого скептицизма тут нет. Есть чёткое понимание термина - абстракция. А насчёт более гибких и безопасных подходов к реализации отличий тут уже обсудили. Наследование общей части, добавляя отличия в потомок - не лучший подход. Паттерн Strategy (он же - Inversion of control. Он же - Dependency injection) есть более гибкий и безопасный метод.
Примеры типа прямоугольников приводилось что бы показать, что не нужно дублировать реализацию общего поведения. То есть те части, которые в фигурах являются одинаковыми с точки зрения используемой абстракции. То что сложности из за отличий возникают, это да. Но фишка в том, что если дублировать общую часть, то сложностей возникает куда как больше. :-)
Логическая суть фигуры очень важна, ибо именно она и диктует её поведение. Смысл ООП проектирования в том и состоит, что надо уметь находить абстракции и выделять из них наиболее общие. Прямоугольник является достаточно общей абстракцией дла квадрата ибо во многом их сущность и поведение идентичны. За одним исключением (равенство сторон).
Если же следовать вашей логике, то абстракций практически нет, ибо у каждого типа есть что-то особенное. И оно действительно есть, вот только смысл абстракций в том, что надо уметь соотносить чего в двух типах больше: сходств или различий.
Вот тут логическая ошибка: ...контракт предлагаемый суперклассом “прямоугольник” утверждает, что, вызывая метод setWidth(), вы измените ширину фигуры и только её...
Дописка ...только её... лишняя. Правильный метод класса должен следить за тем, что бы сохранить сущность этого класса. Посему в прямоугольнике это будет только изменение ширины. А в квадрате и длины также. Но в обоих случая сохраняется важный принцип: меняется ширина и сохраняется логическая суть фигуры.
Код надо писать так, что бы даже случайно его нельзя было испортить. Потому и говорят, что наследование есть не самый удачный подход. И он хуже других подходов. Это, разумеется, не значит что на нём надо ставить крест.
О, пришли неэвклидовы геометры и стали минусовать за то, что назвал квадрат прямоугольником. Видимо аудитория хабра серъёзно молодеет. Пошли волна регистраций из начальных классов и детских садов.
Всё верно, интерфейс можно смоделировать абстрактным классом. Можно даже и обычным. НО! Это потенциально опаснее и мене наглядно. Посему в современные языки и были введены соответствующие ключевые слова.
----------------------------------
Объявим интерфейс Ключ, содержащий метод Открыть.
Объявим класс Поворотный Ключ, реализующий интерфейс Ключ при помощи своих методов Вставить, Повернуть и Вынуть.
Объявим класс Магнитная Карточка, тоже реализующий интерфейс Ключ, но уже по-своему — и без каких-либо неприятных пересечений с реализацией Поворотного Ключа. Этого помогло нам достичь отделение интерфейса от реализации.
Всегда помните об общем принципе: нам нужно использовать не класс, а интерфейс. Нам не важно, что это за штука — поворотный ключ или магнитная карточка, — нам важно, что им можно открыть дверь. То есть, вместо того, чтобы задумываться о природе объекта, мы задумываемся о способах его использования.
----------------------------------
Если же следовать вашей логике, то абстракций практически нет, ибо у каждого типа есть что-то особенное. И оно действительно есть, вот только смысл абстракций в том, что надо уметь соотносить чего в двух типах больше: сходств или различий.
Дописка ...только её... лишняя. Правильный метод класса должен следить за тем, что бы сохранить сущность этого класса. Посему в прямоугольнике это будет только изменение ширины. А в квадрате и длины также. Но в обоих случая сохраняется важный принцип: меняется ширина и сохраняется логическая суть фигуры.
----------------------------------
Объявим интерфейс Ключ, содержащий метод Открыть.
Объявим класс Поворотный Ключ, реализующий интерфейс Ключ при помощи своих методов Вставить, Повернуть и Вынуть.
Объявим класс Магнитная Карточка, тоже реализующий интерфейс Ключ, но уже по-своему — и без каких-либо неприятных пересечений с реализацией Поворотного Ключа. Этого помогло нам достичь отделение интерфейса от реализации.
Всегда помните об общем принципе: нам нужно использовать не класс, а интерфейс. Нам не важно, что это за штука — поворотный ключ или магнитная карточка, — нам важно, что им можно открыть дверь. То есть, вместо того, чтобы задумываться о природе объекта, мы задумываемся о способах его использования.
----------------------------------
Читаем - ...класс Поворотный Ключ, РЕ-А-ЛИ-ЗУ-ЮЩИЙ интерфейс Ключ
Читаем - ...класс Магнитная Карточка, тоже РЕ-А-ЛИ-ЗУ-ЮЩИЙ интерфейс Ключ