Ориентация на объект на основе прототипа. Хороший, плохой, злой?

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

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

В общем, каковы хорошие, плохие и уродливые стороны такого подхода?

"классы объектно-ориентированных языков" - не могли бы вы привести пример языка или двух? «традиционный объектно-ориентированный подход» - можете ли вы привести два примера языка?

S.Lott 22.12.2008 05:53

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

user21037 22.12.2008 13:26

@Dan: Интересное предположение - тот факт, что это неочевидно, означает, что спрашивающий должен предоставить определения или примеры. В противном случае вопрос будет слишком расплывчатым, чтобы ответить.

S.Lott 22.12.2008 15:03
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
10
3
4 625
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

С точки зрения класса POV, класс на самом деле является классом эквивалентности объектов с одинаковыми данными и всеми одинаковыми методами; вы можете рассматривать добавление метода к прототипу как создание нового подкласса.

Реализация проста, но очень затрудняет эффективную проверку типов.

Чтобы сохранить полосу пропускания, вот ссылка на мой ответ на тему «Как я могу эмулировать« классы »в JavaScript? (со сторонней библиотекой или без нее)». Он содержит дополнительные ссылки, а также примеры.

Краткий ответ: сердце прототипа OO JavaScript - это делегирование. В этом стиле ООП разные объекты одного и того же «класса» могут делегировать обработку методов и свойств одному и тому же прототипу (обычно какому-то третьему объекту):

var foo = {
    property: 42,
    inc: function(){
        ++this.counter;
    },
    dec: function(){
        --this.counter;
    }
};
// Note: foo does not define `counter`.

Давайте создадим конструктор для объектов с foo в качестве прототипа. Фактически, все необработанное будет делегировано foo.

var Bar = function(){
    this.counter = 0;
};
Bar.prototype = foo;  // This is how we set up the delegation.

// Some people refer to Bar (a constructor function) as "class".

var bar = new Bar();

console.info(bar.counter);  // 0 --- Comes from bar itself
console.info(bar.property); // 42 --- Not defined in bar, comes from foo

bar.inc();  // Not defined in bar => delegated to foo
bar.inc();
bar.dec();  // Not defined in bar => delegated to foo
// Note: foo.inc() and foo.dec() are called but this === bar
// that is why bar is modified, not foo.

console.info(bar.counter);  // 1 --- Comes from bar itself

Определим inc() прямо на баре:

bar.inc = function(){
    this.counter = 42;
};

bar.inc();  // Defined in bar => calling it directly.
            // foo.inc() is not even called.
console.info(bar.counter);  // 42 --- Comes from bar

Настройка единой цепочки наследования:

var Baz = function(){
    this.counter = 99;
};
Baz.protype = new Bar();

var baz = new Baz();

console.info(baz.counter); // 99
baz.inc();
console.info(baz.counter); // 100

console.info(baz instanceof Baz);    // true
console.info(baz instanceof Bar);    // true
console.info(baz instanceof Object); // true

Аккуратно, а?

console.info (bar.prototype); Разве это не должно быть: bar.property?

Pim Jager 22.12.2008 16:51
Ответ принят как подходящий

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

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

Для советы по использованию объектно-ориентированного проектирования на основе прототипов отличным местом для начала является исходная статья Self о Сила простоты.

Прежде чем беспокоиться о том, как имитировать наследование на основе классов в JavaScript, ознакомьтесь с Прототипное наследование в JavaScript.

Классическое наследование по своей сути ошибочно с точки зрения гибкости, поскольку мы говорим, что «этот объект относится к этому типу, а не к другому». Некоторые языки вводят множественное наследование, чтобы облегчить это, но множественное наследование имеет свои недостатки, и поэтому преимущества чистой композиции перед наследованием (которое в статически типизированном языке является средой выполнения, а не механизмом времени компиляции) становятся очевидными.

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

Таким образом, прототипирование означает более гибкую разработку модулей.

Конечно, совсем другое дело сказать, что разрабатывать ЛЕГКО без статической типизации. ИМО, это не так.

Другие вопросы по теме