Чтобы балбесы, которые не в состоянии изучить математику, могли надувать щи на тему объектно-ориентированности своих убого спроектированных приложений. Классы позволяют размазать логику на много маленьких кусочков, в которых постороннему трудно ориентироваться. А принцип наследования позволяет активно обобщать типы данных по неосновному признаку, например, сделать общий базовый тип для коров, письменных столов и супружеских пар (у них у всех - по четыре ноги). Этому учат даже в учебниках по ООП: дают тебе ромб и квадрат и с умным видом пишут, кто от кого должен наследовать свойства, правда как-то забывают упомянуть, что делать со свойствами, которые наследоваться не должны.
Также классы очень нравятся корпоративным менеджерам, неспособным мыслить дальше своего отдела. Единственный понятный им принцип управления - разделить разработчиков на несообщающиеся друг с другом группы и дать каждой писать свой кусок кода, как если бы вьетнамцы на конвейере шили разные тапочки и складывали их в разные мешки. Естественно, качественный софт таким путём не разрабатывается, т.к. он не рассматривается как единое целое, но зато выполняются кипиаи и кипит бурная деятельность, и всем хорошо.
Другими словами, парадигма ООП идеально ложится на дарвинизм, посредственное корпоративное управление и привычку запутывать код. Что общего у этих трёх дефектов мышления? Они свойственны недоучкам и лентяям. Кстати, Алан Кэй, придумавший ООП, был по образованию биологом, а не математиком, поэтому и втащил в программирование чуждые вычислительным системам свойства, причём в чуждой самой же биологии интерпретации Дарвина.
А конкретные претензии к ООП давно, в общем-то, известны, и распространение этой раковой опухоли только подтвердило их правильность.
Наследование реализации делает приложение тесно связанным, модульность сводится на нет. Логика, хотя и размазана по разным классам, всё равно остаётся чувствительной к малейшим изменениям в любом из них.
Прикрепление кода к данным ухудшает повторное использование кода. Взять, например, STL в C++, в котором алгоритмы отделены от данных. Отсортировать одним и тем же алгоритмом можно массив (array), вектор, представление, диапазон, сишный массив, и вообще любой тип данных, поддерживающий произвольную адресацию. Хочешь - дерево сортируй, только предоставь интерфейс. Аналогично, кучу (heap) можно построить на любом типе данных с произвольной адресацией. А в какой тип пришлось бы запихнуть эти алгоритмы, если бы они реализовывались в парадигме ООП? В какой-то общий базовый тип, который пришлось бы наследовать всем? А для другого алгоритма - другой базовый тип? Вот так на пустом месте и возникает мешанина ненужных связей в приложении. Потому что вместо хорошо проработанной концепции параметрического полиморфизма в ООП используется фальшивка - полиморфизм "для конкретного случая" или ad-hoc.
Иерархии свойств в реальном мире не существует. Поэтому апологеты ООП до хрипоты спорят, кто от кого должен наследоваться в их приложениях, но никогда не могут договориться. Ведь решения нет. "Трейты" (traits - особенности) намного лучше моделируют реальный мир, но они появились позже как попытка устранить основной недостаток ООП. В изначальной концепции их не было.