Почему многие языки динамического программирования с утиными типами используют подход на основе классов вместо ООП на основе прототипов?

23

Поскольку довольно много динамических языков программирования имеют функцию утилитной типизации , и они также могут открывать и изменять методы класса или экземпляра в любое время (например, Ruby и Python ), тогда…

Вопрос 1) Зачем нужен класс на динамическом языке? Почему язык спроектирован таким образом, чтобы использовать класс как своего рода «шаблон» вместо того, чтобы делать его как прототип и просто использовать объект?

Также JavaScript основан на прототипах, но CoffeeScript (расширенная версия JavaScript) выбирает путь на основе классов. И то же самое для Lua (на основе прототипов) и MoonScript (на основе классов). Кроме того, есть класс в ES 6. Итак ...

Вопрос 2) Предполагается ли, что если вы попытаетесь улучшить язык, основанный на прототипах, помимо прочего, вы должны изменить его на класс? Если нет, то почему это так устроено?

ICEX
источник
9
Многие программисты не хотят беспокоиться, узнавая что-то новое. (Это слишком чуждо и "сложно"). Отсюда все те библиотеки на основе классов и языки, которые компилируются в них.
Томас Эдинг
1
Я согласен с Томасом, но забавно то, что после того, как вы освоите динамический подход, на самом деле все становится проще (не сложнее). Концепция объектов все еще существует, просто объекты могут быть изменены без предварительной компиляции какой-то глупой «схемы». Если я хочу поставить пятую ногу на стул, я не хочу сначала изменять план, я просто хочу добавить ногу. На мой взгляд, динамические языки более точно моделируют реальность.
Лонни Бест
1
ООП был изобретен в статически типизированном контексте, где типы должны быть объявлены. Там классы - разумный шаг вперед от записей и модулей. ООП на основе прототипов всегда было интересной темой для изучения языка Self, и каким-то образом превратил его в JavaScript как самый простой способ пометить модное слово «ООП» для практически функционального языка. Приятно то, что вы можете реализовывать классы поверх прототипов. Хотя мне нравятся метаобъекты, отделение классов от их экземпляров облегчает написание хорошо продуманного, простого, слабо связанного кода.
Амон
3
Перво-наперво: сам JavaScript поддерживает classключевое слово в следующем стандарте ECMAScript (ECMAScript 6). Поддержка классов в JavaScript планировалась давно. Теперь, что это такое - классы - это просто синтаксический сахар, проще рассуждать о модели для объектов одного типа. Именно так в JS и так в Python и других динамических языках.
Бенджамин Грюнбаум
1
@BenjaminGruenbaum "... классы - это просто синтаксический сахар ..." вау, для меня это довольно новая идея, действительно, для таких языков, как ruby ​​и python, кажется, что не имеет значения, использовать объект или класс в качестве шаблона - оба могут быть изменены на лету в любом случае. И не важно, как они справляются с наследством. Так что, возможно, нет необходимости проводить различие между подходом на основе классов и подходом на основе прототипов для динамического языка :)
iceX

Ответы:

12

Вопрос 1) Зачем нужен класс на динамическом языке? Почему язык спроектирован таким образом, чтобы использовать класс как своего рода «шаблон» вместо того, чтобы делать это как прототип и просто использовать объект?

Самый первый язык ОО (хотя он не назывался "ОО"), Симула, не имел наследства. Наследование было добавлено в Simula-67, и оно было основано на классах.

Примерно в то же время Алан Кей начал работать над своей идеей новой парадигмы программирования, которую он позже назвал «объектно-ориентированная». Ему действительно нравилось наследование, и он хотел, чтобы оно было на его языке, но он также не любил занятия. Однако он не мог придумать способ получить наследование без классов, и поэтому он решил, что ему больше не нравятся классы, чем наследование, и разработал первую версию Smalltalk, Smalltalk-72 без классов и, следовательно, без наследования.

Пару месяцев спустя Дэн Ингаллс придумал дизайн классов, где сами классы были объектами, а именно экземплярами метаклассов. Алан Кей счел этот дизайн несколько менее ужасным, чем старые, поэтому Smalltalk-74 был разработан с классами и с наследованием на основе классов.

После Smalltalk-74 Алан Кей почувствовал, что Smalltalk движется в неправильном направлении и на самом деле не представляет, что такое ОО, и предложил команде отказаться от Smalltalk и начать все сначала, но за него проголосовали. Таким образом, последовали Smalltalk-76, Smalltalk-80 (первая версия Smalltalk, которая будет выпущена для исследователей) и, наконец, Smalltalk-80 V2.0 (первая версия, которая будет выпущена на коммерческой основе, и версия, которая стала основой для ANSI Smalltalk) ,

Поскольку Simula-67 и Smalltalk-80 считаются прародителями всех ОО-языков, почти все последующие языки слепо копировали дизайн классов и наследование на основе классов. Пару лет спустя, когда появились другие идеи, такие как наследование, основанное на миксинах вместо классов, и делегирование, основанное на объектах, а не наследование, основанное на классах, наследование на основе классов уже стало слишком укоренившимся.

Интересно, что нынешний язык Алана Кея основан на делегировании прототипов.

Йорг Миттаг
источник
"... текущий язык Алана Кея ..." который ...?
Хавьер
@Javier: я не думаю, что у него есть имя, а имя системы постоянно меняется.
Йорг Миттаг
Это должно быть хорошим ответом, чтобы указать на следующий раз, когда кто-то перечисляет наследование как требование для ОО :)
Привет
1
@iceX: Алан Кей основал Исследовательский институт Точек зрения для работы над своими идеями. К сожалению, информация действительно разбросана по сайту.
Йорг Миттаг
3
Цитата Алана Кея о OO: «Для меня OOP означает только обмен сообщениями, локальное хранение и защиту, а также скрытие процесса состояния и крайнюю позднюю привязку всех вещей. Это может быть сделано в Smalltalk и в LISP. Возможно, существуют другие системы в что это возможно, но я не знаю о них ".
Джоери Себрехтс
23

Многие программисты предпочитают работать с классами. Это очень простая для понимания концепция, которая является хорошей моделью человеческих мыслительных процессов о мире (то есть мы инстинктивно связываем реальные объекты с абстрактной группой предметов, к которой мы считаем их принадлежать, то есть с классом) , Кроме того, классы упрощают рассуждения о типах объектов: в языке на основе классов применение принципов, таких как подстановка Лискова, проще, чем в языке, где у нас просто есть объекты, которые могут иметь разные методы или тип которых может даже измениться во время выполнения. , как в случае с JavaScript.

Обратите внимание, что даже в JavaScript очень много кода просто использует прототип для эмуляции классов. Это в основном потому, что многие программисты предпочитают так думать.

Существует также другая причина, по которой предпочтительны языки на основе классов: их проще скомпилировать в эффективный код. Наиболее эффективные виртуальные машины JavaScript эффективно динамически создают классы для представления типов объектов JavaScript по мере изменения их методов и прототипов. Посмотрите это описание реализации V8 для обоснования того, почему это делается.

Жюль
источник
4
Ваш последний абзац фактически полностью противоположен тому, что вы говорите: V8 доказывает, что вам не нужны классы в языке для компиляции в эффективный код на основе классов.
Йорг Миттаг
4
Да, они вам не нужны - но тот факт, что V8 (и, вероятно, Self, хотя я не слишком много читал о дизайне этой системы) эффективно создает виртуальные классы, означает, что начинать с языка, который использует классы по своей природе, почти конечно, проще, и поэтому, вероятно, в конечном итоге JIT придется тратить меньше времени на компиляцию кода.
Жюль
11
Конечно, и тот факт, что V8 эффективно создает GOTOs и регистры, означает, что просто отказаться от всех абстракций и писать непосредственно в сборке почти наверняка проще, и поэтому, вероятно, в конечном итоге JIT потребуется меньше времени на компиляцию кода. Работа компилятора заключается в поддержке абстракций более высокого уровня.
Йорг Миттаг
1
Да, но это компромисс, так как абстракция более высокого уровня в большинстве случаев сложнее реализовать и часто приводит к снижению производительности во время выполнения, особенно при работе с JIT, а не с компилятором AOT. Я подозреваю, что многие разработчики языка выбирают основанную на классе структуру по одной или обеим из этих причин; Я знаю, поэтому я выбрал классы с фиксированными членами для (в противном случае динамического) языка, над которым я работаю, но могу только строить догадки о других языках.
Жюль
1
Я бы сказал, что программисты предпочитают «думать на уроках» только потому, что так учат большинство из нас. Я, конечно, могу вспомнить многих моих сокурсников в колледже, которые в течение нескольких лет испытывали трудности в понимании и понимании некоторых действительно фундаментальных объектно-ориентированных концепций. Это только кажется очевидным и легким в ретроспективе.
KChaloux
3

Я слышал, что в больших проектах, где команды людей работают вместе над одним и тем же кодом, эти гибкие языки (где вы можете изменять свойства и методы объекта во время выполнения) - это свободы, которые другие члены команды не хотят, чтобы вы иметь.

Они хотят знать, когда они имеют дело с объектом, что объект будет действовать точно так же, как говорит план, а не каким-то измененным способом, которым какой-то другой амбициозный разработчик решил изменить его, чтобы выполнить свою собственную задачу.

Итак, единственная причина, по которой я могу представить, что кому-то не нужны гибкие возможности, предлагаемые этими удивительными динамическими языками, заключается в том, что они хотят упростить командную разработку, отладку и автоматическое документирование.

Лично я разработал приложения в обеих методологиях, и с динамическими языками я справляюсь быстрее. Я не использую ни одну из этих платформ, предназначенных для того, чтобы снова превратить мой динамический язык в язык классов. Такие вещи являются регрессом на мой вкус.

Лонни Бест
источник
1

Для меня ООП означает только обмен сообщениями, локальное хранение, защиту и сокрытие процесса состояния и крайнюю позднюю привязку всех вещей - Алан Кей

Так что он говорит здесь о том, что ОО - это создание черных ящиков, которые отвечают на сообщения. В некотором смысле, REST является конечной ОО-системой в том смысле, что она использует глаголы (т.е. сообщения) и ресурсы (то есть непрозрачный блок, содержащий некоторые данные).

Таким образом, вопрос о том, почему некоторые основаны на классах, а другие на прототипах, упускают из виду тот факт, что на самом деле это не имеет значения, они оба просто реализации. Система, которая использует исключительно обмен сообщениями вместо вызовов методов, является такой же ОО, как и два упомянутых вами экземпляра.

gbjbaanb
источник