Комментарии 53
И ты, Брут?
Парадигмы в программировании понадобились, чтобы упоавлять сложностью, чтобы упростить восприятие кода в частности. Разработчику надо быть хоть немного архитектором, чтобы осознанно выбирать тот или иной подход в реализации решения. Там где объекты уместны, там применение ООП снижает нагрузку и повышает эффективность ппрограммиста. А в статье очередное нытьё!
Разработчику надо быть хоть немного архитектором, чтобы осознанно выбирать тот или иной подход в реализации решения. Там где объекты уместны, там применение ООП снижает нагрузку и повышает эффективность программиста.
Точно!
Поэтому считаю, что: «объекты и классы – дар Божий». Они очень хорошо позволяют структурировать код, выносить модули в автономные классы. А там, где слегка накосячил в первой версии программы, как у меня:

то, используя более трезвый подход, можно, на тех же принципах, ваять уже усовершенствованную версию своей программы, что я, сейчас, и делаю.
Люто плюсую, статья явно написана без ИИ!
В ООП языках объекты часто стали превращаться в минибиблиотеки функций. И в проектах чаще вижу в коде не объекты, а дтошки с сервисами. Отделены код и данные. Наличие ООП объектов в коде не приводит автоматически к правильной модульности и минимизацией зависимостей. Это лишь один из способов структурирования кода. И не самый простой. Один разработчик считает, что документ должен иметь метод "Печатайся" с передачей ему объекта, куда печататься. Другой считает, что должен быть объект Принтер, имеющий метод "печатать", принимающий документ на вход. Это серьезная когнитивная нагрузка, каждый раз выбирать. ООП легче все же при симуляции конкретного процесса, лучше физического.. Там легче выбирать, так как ты его отчасти копипастишь с природы. Но когда ты имеешь дело с данными, которые живут в разных процессах, и могут пережить старые процессы, перекатившись в новые, то, гораздо проще иметь дело со более универсальными структурами данных и функциями, умеющими работать с ними. Но это мое личное мнение, не больше. У меня есть статья, тоже написанная на эмоциях на эту тему )
Пример, конечно, неудачный. Метод можно поместить куда угодно если он не трогает потроха класса и у нас вообще нет наследования. Что явно вырожденный случай. Если наследование есть, и оно предполагает разную реализацию печати для разных принтеров или для разных документов - то расположение метода очевидно.
Ну а разные процессы - это объекты обёрнутые в JSON-ы, вроде бы так.
Во-первых. "Есть несколько разных реализаций этого вызова.... Это ещё зовут полиморфизмом"
Вроде бы это зовут абстракцией?
Во-вторых, насколько я знаю, "a table" значит "какой-то инстанс", или "некий инстанс". Класс это просто table, без артикля.
Безусловно , ООП это не свойство языка, свидетельством чего являются первые версии Windows: ООП в чистом виде, и при этом на ANSI C.
На моих первых работах я в основном писал свой код, с нуля или почти с нуля. Я очень любил ООП и С++: все можно было сделать проще и понятнее. Потом так получилось, что я в основном читал чужой код и чинил там баги или делал небольшие добавки. И тут я ООП разлюбил. Когда длинная цепочка наследования, происходит что-то непонятное, и поди знай, откуда это выплывает, с какого уровня... Когда в суперклассе есть то, что мне нужно, а я не могу это использовать, потому что метод не protected, a private...
Как то раз в коде было написано что-то типа "х := у + 1". Результат: у был 0, х стал -1. Сначала я решил, что у меня сломался процессор :-) Оказалось, нет: кто-то перегрузил операторы "-" и "+", и в определённых условиях они срабатывали наоборот.
Это проблема реализации ООП в ++. Собственно, поэтому в Java и большинстве последующих языков перегрузку операторов отменили.
Насчёт "какой-то инстанс" Вы правы, но это и есть введение класса, по сути. Мы не знаем конкретных свойств этого инстанса (значений полей и даже конкретного класса). Ну, то есть, даже не знаем, кухонный это тейбл, или верстак.
Вообще-то в Линуксе издревле основным понятием был процесс, а не объект. А по поводу парадигм и программирования существуют и другие мнения. Например здесь: http://softcraft.ru/
не столько некое замечание, сколько некая мысль, о которой я подумал во время чтения статьи
отдельно интересно мыслить из категории ооп без наследования классов, как в расте или хаскеле; а то и вовсе некую вырожденную категорию где есть строго только синглтоны ну или каждую структуру можно "инстанцировать" лишь единожды
по сути, исходя из такой, каждый объект характеризуется лишь своими свойствами. есть интерфейс/трейт "стул", характеризующийся тем что на нём можно сидеть и ещё какими-то свойствами.
есть трейт "деревянный стул" — по сути, объединение трейтов "стул" и "деревянный объект" + какие-то свои отдельные свойства.
и есть некий объект "The деревянный стул сделанный на фабрике в Швейцарии в 1998 году пекарем Николой Теслой во время запекания сапогов, украденных у соседки Зины, пока она …, масса которого составляет 10кг, состоит в данный момент из x.xE+27 атомов, …" — каждый такой объект уникален и каждый удовлетворяет каждый лишь строго своему набору трейтов.
каждый трейт это просто объединение других трейтов (ну или какой-то атомарный трейт по типу как условный трейт "объект со скоростью 1 м/с"), а каждый объект это некая уникальная сущность
хотя возможно, для такой модели ближе не oop, а ecs. тогда, сервисы — это те самые трейты, а компоненты… не уверен. возможно, сервисы — тоже компоненты, просто динамические? а объекты это как раз entity.
впрочем, из конкретно примера со стулом, можно ещё и привести непонятки, навроде парадокса корабля тесея… ну или что если взять половину атомов стула и использовать для создания одного стула, а половину для создания другого… будет ли хоть один из новых стульев считаться оригинальным объектом? как будто тогда уж стоит говорить и о уникальности во времени, ну или иммутабельности, что, как мне кажется, точно лишь запутывает…
Можно практически всё, но зачем? Наследование - способ структуризации и представлений о предметной области, и связанных с ним применимых к ней алгоритмов. Представить себе мир, где объекты компонуются из необъятного моря трейтов легко, но они же не будут ортогональны. Придётся сделать трейт "украдены у Зины" и трейт "украдены у Люси", вместо трейта "украдены у кого-то" и его конкретизации.
Я делал в своё время в Яндексе иерархическую ОО БД, в которой иерархия была именно и только иерархией наследования. То есть в ветке дерева можно было либо заявить новое свойство, либо зафиксировать значение заявленного выше свойства. Оказалось, что иерархия наследования самодостаточна и позволяет заменить собой иерархию хранения.
Это, конечно, немного взрывало мозг, но логика была безупречна. (Она делалась для Маркета) - на каждом уровне иерархии появлялись поля, актуальные для данного обобщения. И, кстати, множественное наследование работало и позволяло из "принтеры" и "сканеры" родить "МФУ".
Но тезис «ОО очень хорошо ложится на окружающий мир» — не подтвержден буквально ничем. Меж тем, Аланкаевская модель с сообщениями — вот она действительно блистательно описывает мир, ибо объекты гораздо менее важны, в сравнении с обменом информацией. ОБ этом очень много говорил Армстронг, и его реализация «окружающего мира» — гораздо убедительнее Гослинговой.
За это вам наша искренняя сердечная благодарность!
Настоящий ("аланкеевский") ООП не просто хорошо, а изумительно хорошо описывает буквально всё. При этом всего-то и нужны объекты и сообщения.
Универсальность * Простота = МОЩЬ
И не нужны никакие краденые и переиначенные инкапсуляции, полиморфизмы, которые только усложняют и путают. И даже наследования с абстракциями совсем не обязательны. Это всё прекрасно выводится из объектов и сообщений.
Современный "ООП" на столько исковеркал саму идею, что все эти споры остроконечников с тупоконечниками уже просто смешны — про то, что яйцо вариили, чтобы его просто съесть, никто даже не вспоминает. …Нет, уже даже и не знает, похоже.
"Минимальный понятийный аппарат" — это вы про полиморфизм и инкапсуляцию? А я почему-то думал, понятийный аппарат должен быть хотя бы более однозначным и более простым, чем то, для описания чего он используется.
Как странно получается… Про сообщения и объекты вы в курсе. Про то, что на их основе сделаны Smalltalk/Self, Erlang (с оговорками, но всё же) и акторы — видимо, тоже? Про то, что "инкапсуляция" с "полиморфизмом" в отношении ООП появились позже, наверное, как минимум, догадываетесь. Но для описания очевидных следствий из "аксиоматики" всё равно почему-то считаете необходимым введение "понятийного аппарата" на основе переусложнённого и искажённого "полиморфизма" и шизофреничной "инкапсуляции". А чем они лучше простейших и интуитивно понятных, наверное, любому школьнику "поведения" и "состояния"? В последних по вашему мнению чего-то не хватает? Чего?
Дайте угадаю, вы никогда не сталкивались с понятийными аппаратами современной математики (всякие там аффинные геометрии, теории групп, и т. п.).
Не угадали.
Все эти понятийные аппараты именно упорядочивают и упрощают — то есть убирают избыточную сложность, а не добавляют её. Они появились по необходимости — без них просто не удавалось получить желаемое (формализованные доказательства).
Тем, что помимо аксиоматики любой теории нужен набор теорем, иначе в аксиоматике Пеано замучаешься каждый раз с нуля доказывать коммутативность.
Я же про это и спросил! Только не про аксиоматику Пеано, а про аксиоматику ООП.
Какое утверждение провозглашает "теорема" под названием "полиморфизм" в ООП? Что она даёт, чего не даёт на порядки более простая пара утверждений: "одно и то же сообщение может быть по-разному обработана разными объектами" и "один и тот же объект может по-разному обработать одно и то же сообщение в разные моменты времени"? Зачем мне может понадобится для определения (sic!) понятия ООП начинать ссылаться на "способность функции обрабатывать данные различных типов", строя искусственные изоморфизмы из пространства объектов и сообщений в пространство функций, данных и типов? А затем перечислять все виды и подвиды полиморфизма, добавляя ещё больше бессмысленной избыточности?
(В классическом определении ООП через объекты и сообщения, дополненного вариантом реализации через поведение и состояние не хватает…) Прилагательных и наречий :) Поведение — это глагол. Состояние — существительное. И пока мы с вами — не Бродский, — нам не обойтись одними глаголами. «Красный» — это не поведение и не состояние.
"Красный" — это именно состояние, которое влияет на поведение.
И как же полиморфизм с инкапсуляцией позволяют добавить прилагательные и наречия?
И ещё интересно, как же, по вашему мнению, без них древние смогли создать, например, Smalltalk, который до сих пор по выразительным/функциональным возможностям и простоте минимум на порядок превосходит все ополиморфленные и обинкапсулированные якобы ООП-шные современные языки? ;)
Есть гипотеза, что я понял, наконец, что вас так выводит из себя.
Меня ничто не выводит из себя. Я всегда в себе, что бы со мной ни происходило ;) И уж точно повальное извращение ООП не может вывести из себя — я всё ещё продолжаю удивляться, как можно, но уже почти не верю, что это всё можно изменить :)
Я использую термин «полиморфизм» в качестве синонима для /…/
Я всё больше склоняюсь к тому, что использование одних и тех же слов для обозначения разные вещей — одна из основных проблем человечества :D
Попробуйте открыть статью "Полиморфизм (информатика)" в Википедии, и должно стать понятно, что и почему я понимаю под термином "полиморфизм".
И я бы тоже с удовольствием сокращал количество фрикций в фалангах своих пальцев, ограничившись словом "сообщение", но почему-то это всякий раз приходится объясняться…
Сути это, впрочем, не меняет.
Ну, вот как?! Как использование слов не по их исходному значению может не менять сути?
Как можно просто брать и использовать термин "полиморфизм", у которого есть вполне определённый (хотя и очень сложный) смысл, преданный этому термину ещё до появления термина "ООП", для краткой передачи смысла сообщений? Да ещё и учитывая, что с помощью этого термина переврали, извратили и буквально поставили с ног на голову всю концепцию? :)
Как можно говорить, что Кэй "дистанцировался" от ООП, используя «genericity», если Кэй с помощью этого термина пытался объяснить смысл ООП, (безрезультатно) демонстрируя, что "полиморфизм" (несмотря на всю сложность) не в состоянии дать те же возможности, что и концепция ООП и сообщений?
Не понимаю как, но вот вижу, что можно: именно так и превратили ООП в того уродца, о котором нынче ломают копья "тупоконечники" с "остроконечниками". И нет, это не выводит меня из себя. Скорее, уже забавляет ;)
Да окститесь, в смолтолке полиморфизм был с первого дня.
Вы про какой полиморфизм? Тот, который сейчас используют для "объяснения" что такое "ООП" — но который при про функции, а не про сообщения? Или всё же про ваш личный, который вы каким-то образом привязываете к связке объект-сообщение?
И про первый день какого именно Smalltalk-а речь? Про Smalltalk-80? Или про Smalltalk-76? Или, может быть, про Smalltalk-72? Было бы интересно услышать, как вы к нему привяжете полиморфизм… Или вообще про концепцию 71-го года — это было бы даже интереснее.
…Хотя, вы же, наверное, привяжете полиморфно — наделив термин "полиморфизм" ещё какой-нибудь интерпретацией? :)
> как же полиморфизм с инкапсуляцией позволяют добавить прилагательные и наречия?
Трейтами, например. Еще раз: я оперирую сущностями, а не ООП-шными паттернами.
По всей видимости, под "прилагательными" и "наречиями" вы тоже имеете ввиду что-то другое — не то, что в учебниках по русскому языку? Можно считать этот вопрос риторическим :)
Вот я тоже почитал и подумал - Вас именно эти слова, что ли, бесят? Ну - полиморфизм - это общепринятое сокращение для "одно и то же сообщение может быть по-разному обработана разными объектами" - почему это так раздражает-то?
Потому что Вас раздражает само слово ООП?
Вот смотрите. Формально Вы совершенно правы - если всё вокруг народное immutable - инкапсуляцию можно отменить, верно?
Во-первых, неверно. Инкапсуляция, в том числе, скрывает трюки реализации, которые действительно знать нельзя. Мне один из сотрудников Микрософта рассказывал, что программисты просекли, что при старте процесса в Windows в каком-то регистре всегда лежит что-то полезное - какой-то дескриптор. И начали им пользоваться. А это значение там лежит случайно - валяется потому что последнее вычисление его использовало. Код скорректировали - и оно пропало. И Вы не представляете, на сколько денег влетел Микрософт, чтобы СИМУЛИРОВАТЬ это поведение для программ, которые от него сдуру зависят.
Отсюда некоторый максимализм, который иногда звучит в ООП - извне реализации даже классы желательно не использовать, только интерфейсы.
И вторая часть - ну, положим, мы такие заиньки, что трюки реализации ну никак не светятся. Не верится, но положим. Вот только есть беда - как обсуждаешь ФП формально, так в нём присваивания нет. А как реализация и конкретный код - так и сразу есть. И сразу - "это только критики ФП требуют от него идеального соответствия канонам, а мы, носители тайного знания, уже давно считаем, что присваивать можно". Это почти буквальная цитата из дискуссии.
Так что - можно бы в рай заменить инкапсуляцию иммутабельностью, да грехи не пускают.
С точки зрения процесса этот регистр immutable - это внешние константные для него данные (менять их в ядре ОС он не может, видит копию), и проблема ИМЕННО в том, что процесс увидел чужой стейт. Который должен был быть недоступен. Увы, иммутабельность не заменяет инкапсуляции - не всё то, что нельзя изменить можно видеть и использовать.
Смотрите. Конкретизация до значений - это я немножко жёстко заявил, но дело в том, что наполнение поля значением тоже порождение дочернего класса, с некоторой точки зрения. Но можно не лезть в эти детали. Собственно, если трейты наследуются - то это ООП с множественным наследованием, а если не наследуются - это кабздец без реюза кода.
Вы, кажется, не уловили сути статьи. Она в том, что есть вещи естественные для человека, а есть неестественные. И вот duck.sound - естественная. Потому что утка крякает. А не шум издать утка. Не мыслят люди так. ФП тут не при чем, оба примера вполне императивны. Мало того, если Вы когда-нибудь ныряли в чужой код, то должны различать "посмотреть все методы утки" и "посмотреть все функции на свете, которые принимают что-то типа утки". Первое легко, второе нереально.
В другом комментарии уже и так всё объяснили но всё же, объясню и от себя
Придётся сделать трейт "украдены у Зины" и трейт "украдены у Люси", вместо трейта "украдены у кого-то" и его конкретизации.
trait Stolen {
const from : &str;
}
// или так, игнорируя, что константным параметром могут быть только инты, предполагая что объект может быть украден по нескольку раз
trait Stolen<const from : &str> {}в идеале, если будут зависимые типы, позволяющие сделать константы не такими уж и константами — что хорошо ляжет на изменчивость при использовании разных объектов. Потом может появиться что-то такое :)
И, кстати, множественное наследование работало и позволяло из "принтеры" и "сканеры" родить "МФУ".
Вообще я немного думал о наследовании и мне кажется, что возможность наследовать только методы (интерфейсы) полностью покрывает возможности наследования с полями. А если базовый класс позволяет задавать поведение (как делают Unity или Javafx), его тогда странно, что с самого начала не заменят на пару из композиции и наследования от некого интерфейса/трейта
// вместо
abstract class Parent {
int a;
}
class Child : Parent {
...
}
//делать как-то так
interface Parent {
protected int a {get; set;}
}
sealed class Child : Parent {
// бонусом ещё и видно на месте,
// так что не придётся лезть в базовые классы за определением
protected int a {get; set;}
...
}но наверное, в бд это может быть какой-то отдельный случай, где было удобно сделать именно так, я не сталкивался с таким, наверное.
да возможно моя мысль окажется непрактичной, я не могу сказать.
Можно, вообще, отдельно обсуждать наследование интерфейса и реализации, и второе часто делается именно композицией.
Тут проблема вот в чём. Если бы ортогональность унаследованных интерфейсов была гарантирована и гарантировала бы ортогональность реализаций, то мир был бы прекрасен. В реальности сам факт того, что нам надо совместить два интерфейса означает, что реализация будет не "сложить вместе две реализации", а как-то их связать.
Если бы к "фиговым" трём пунктам добавить ещё и самый неправильный про то, что "ООП — это инкапсуляция, наследование, полиморфизм", могло бы получиться что-то дельное. А так, к сожалению, получился очередной наброс в спор глухих со слепыми о балете.
Предполагается, что уж определения с первой страницы букваря читатель знает. :) Читателю, который этого не знает и сам вопрос, наверное, не очень интересен...
Кто-то кого-то не понимает — либо я вас, либо вы меня. Давайте выясним:
Буду краток - все три пункта выше - фи-игня.
Вот и четвёртый (я бы его на первое место поставил) пункт про инкапсуляцию, наследование, полиморфизм — не меньшая фи-игня. Да?
Э. Стоп. Это общепринятое определение. Его можно тоже снести, но тогда надо свое предложить. Я такой задачи перед собой не ставил.
Всё уже давно предложено. С самого начала. И благополучно забыто.
В целом, позиция ясна.
Вы не путаете "забыто" и "умерло"? Динозавры не забыты, но исчезли - не конкурентоспособны. Так и с ООП - оспорено множество раз, но живёт, а конкуренты - если они вообще без ООП - умирают. И я объяснил, почему - потому что ООП соответствует базису мышления человека. И да (и про это я там тоже написал) - реальное ООП неидеально и местами коряво. А теперь посмотрите на русский и английский язык - неидеальны и местами корявы. Посмотрите на понятийный аппарат среднего homo sapiens. На этот мир, вообще.
:)
Вы не путаете "забыто" и "умерло"?
Нет. Но что вы понимаете под "умерло" — я понять не смог. Я-то всего лишь говорил о том, что исходная идея ООП существенно отличалась от "общепринятой" сейчас. И нет, она не умерла — просто забыта. И это печально, потому что она обладает гораздо большими выразительным возможностями, но при этом ещё и проще.
ООП соответствует базису мышления человека.
С этим утверждением я, в общем-то, согласен. Правда, не совсем уверен, что правильно понимаю, что вы имеете ввиду под "базисом мышления"… Но зато теперь уже практически полностью уверен, что "ООП" у вас и у меня — очень разные. Так что:
Тот ООП, который (как я понимаю) имел ввиду Алан Кэй, придумывая этот термин, — да, похоже, является "базисом" человеческого мировосприятия.
Тот ООП, который про полиморфизм-инкапсляцию-наследование, — нет, таким базисом не является, и не может являться: слишком сложно и слишком узко для "базиса". И это "ООП" обречено постоянно "бодаться" с ФП и прочими в попытке обосновать и защитить себя, вместо того, чтобы стать эмерджентным синтезом.
Ну - значит, ждём новый ЯП...
Зачем? Зачем создавать что-то новое, пока нет понимания уже существующего?
…Даже, правильнее сказать, "существующИХ". Потому что после Smalltalk-а были и Self, и Strongtalk, и Newspeak… и даже Erlang с Elixir-ом. В общем были, были попытки развития разной степени успешности (разумеется, здесь я не имею ввиду популярность) — именно на основе понимания идеи ООП.
Но большинству милее деградация через всякие С++, Java и прочие химеры. Неадекватность заложенных в основу подобных ЯП принципов, "идеям ООП" (которые они тщатся "воплотить") компенсируется извращением и вырождением этих самых идей. Зато Algol-истый синтаксис — он же такой знакомый и "простой" (точнее, привычный) в реализации. Не зря же в ВУЗах основы теории компиляторов преподают. …Или уже не преподают?
А ещё можно очень успешно критиковать то, что не понимаешь. Особенно, если не хочешь понимать. Это ведь очень удобно делать, когда вокруг столько уродливо-кривых воплощений. Железная же "логика": идея —> извращение идеи —> воплощение извращённой идеи —> провал => вывод: идея была неправильной. Столько простора для "творчества"!
Так что ждать новых ЯП не приходится. А если они появятся, вряд ли это будет шагом вперёд для ООП.
Зато можно ожидать повторения раундов борьбы инкапсуляции с иммутабельностью и наследования с полиморфизмом. Это — всегда пожалуйста, это — сколько угодно! :D
Что-то в этом есть. Чем не классы?
module type ACC = sig
type t
val add: string -> t -> t
end
module NoAcc = struct
type t = unit
let add _ () = ()
end
module type DEPS_ENV = sig
module Acc: ACC
val deps: unit -> JSON.value
val name: JSON.value
val yes: bool
end
module Deps = struct
module A = Set.Make(String) (* implements ACC *)
(* A bit of an artificial example *)
module Inherit = struct
include A
let add k x = prerr_endline "Inherited" ; A.add k x
;;
endС автором в целом согласен: объектность действительно не была “изобретена” объектно-ориентированными языками, а во многом была ими формализована и поддержана на уровне синтаксиса и инструментов.
Но есть одно терминологическое уточнение. В статье, местами смешиваются типы и классы. Из-за этого тезис “человек мыслит классово” становится чуть менее точным.
Я бы сказал иначе: человек в естественном языке чаще мыслит не классами, а типами - причём контекстными и довольно мягкими. “Стул”, “мебель”, “ключ”, “документ”, “ребёнок” - это не столько классы в объектно-ориентированном смысле, сколько типы использования внутри некоторого фрейма.
Например, ящик может быть “стулом” в контексте “на чём сидеть”, но не быть стулом в контексте “покупаем мебель”. Один и тот же объект может одновременно попадать в разные типы в зависимости от задачи: стол может быть мебелью, поверхностью, препятствием, товаром, семейной реликвией или средством спасения при наводнении.
Класс в программировании обычно задаёт реализационный шаблон: как объект устроен и как создаётся. Тип же задаёт допустимое использование: какие операции с этим значением имеют смысл. В естественном языке мы чаще работаем именно со вторым: не с жёсткими классами объектов, а с рамками допустимого обращения с ними.
Поэтому я бы переформулировал центральную мысль так: человек мыслит не столько объектно-классово, сколько типами и фреймами. А объектно-ориентированное программирование - это одна из инженерных попыток сделать такую типизацию мира более жёсткой, формальной и исполнимой машиной.
Я бы сказал иначе: человек в естественном языке чаще мыслит не классами, а типами - причём контекстными и довольно мягкими.
А вот я, например. не мыслю ни классами, ни типами. Может быть, я в этом разительно отличаюсь от всего остального человечества… но почему-то очень сильно сомневаюсь в этом.
Если я очень устал и хочу присесть, то я не ищу вокруг объекты типа стул. И объекты класса Стул тоже не ищу. Я ищу то, на что я могу присесть. И если рядом окажется не стул, а табуретка, то вряд ли я откажу своим ногам в отдыхе по причине несовпадения типа.
А когда мне нужно отпереть дверь, то я не ищу "какой-нибудь ключ" — я ищу конкретный ключ, который может отпереть данный конкретный замок. И это не мешает кому-то воспользоваться отмычкой. А кому-то просто выломать дверь. И при этом я могу использовать ключ от дверного замка, например, для того, чтобы проткнуть и вскрыть конверт при отсутствии поблизости ножа.
Вы же что-то подобное имеете ввиду, когда делаете оговорку о том, что типы "контекстные и довольно мягкие"?
И вообще, зачем всё (пере-)усложнять и придумывать новые смыслы для понятий, созданных для другого? Как вы верно заметили, классы нужны именно для создания объектов. Но в ООП можно обойтись и без них. А типы были придуманы для выделения нужного объёма памяти. В реализации ООП на современных компьютерах без этого обойтись, конечно, сложнее, но сама суть идеи ООП на типа никак не завязана, и в объектном языке тоже вполне можно обходиться без них.
"Объектная ориентированность" заключается ни в классах, и ни в типах — она заключается в том, чтобы из окружающего мира выделять объекты и взаимодействовать с ними. И ООП уж точно не создавалось, чтобы "сделать … типизацию мира более жёсткой, формальной…". Кэй преследовал, скорее, как раз обратную цель — избавиться от навязываемой машиной излишней жёсткости и ненужной формализации, спрятав её внутри объектов, а связи между ними сделать максимально гибкими и раскрепощёнными за счёт (динамически интерпретируемых) сообщений.
А типы были придуманы для выделения нужного объёма памяти.
Типы были "придуманы" еще в докомпьютерную эпоху
И классы были придуманы еще в докомпьютерную эпоху… И объекты. И сообщения… И вообще почти всё было придумано в докомпьютерную эпоху. Даже сами компьютеры тоже были придуманы в докомпьютерную эпоху :D
Что с того? Речь о том, какой смысл был вложен в понятие уже при историческом материализме "в компьютерную эпоху".

Объекты и классы — дар божий или проклятие