Какие школы ООП? [закрыто]

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

var delayedFORLoop = function (array) {
    var defer = $q.defer();

    var loop = function (count) {
        var item = array[count];

        // Example of a promise to wait for
        myService.DoCalculation(item).then(function (response) {

        }).finally(function () {
          // Resolve or continue with loop
            if (count === array.length) {
                defer.resolve();
            } else {
                loop(++count);
            }
        });
    }

    loop(0); // Start loop
    return defer.promise;
}

// To use:
delayedFORLoop(array).then(function(response) {
    // Do something
});

Пример также доступен на моем GitHub: https: //github.com/pietervw/Deferred-Angular-FOR-Loop-Example

29
задан AraK 17 July 2009 в 15:25
поделиться

9 ответов

Несколько ключевых «отличий» в «Стиле» внутри более широкого баннера ООП.

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

Полиморфное позднее связывание

или «что означает foo.Bar(x)

  1. Иерархия типов сводится к конкретной реализации в каждом случае (часто делается через vtable ) и часто допускает явную ссылку на реализацию базовых классов.
    • Концептуально вы смотрите на наиболее конкретный тип, который foo находится на месте вызова. Если он имеет реализацию Bar для вызываемого параметра x, если не выбран родительский элемент foo, и процесс повторяется.
    • Примеры: C ++ / Java / C #, « Simula style » часто используется.
  2. Чистая передача сообщений. Код в foo, который обрабатывает сообщения с именем «Bar», должен принять x. Только имя имеет значение, а не какие-либо предположения, которые сайт мог сделать о том, каким должен был быть Бар. В отличие от предыдущего стиля, в котором рассматриваемый метод представлял собой Bar, который, как известно, определен во всем, что было известно об иерархии типов, определенной во время компиляции (хотя точное место в иерархии оставлено до времени выполнения).
    • Примеры: Objective-C / Ruby, « Smalltalk style » часто используется.

1 часто используется в статически типизированных средах, где это ошибка, проверяется во время компиляции на отсутствие такой реализации. Кроме того, языки часто различают Bar (x) и Bar (y), если x и y - разные типы. Это перегрузка методов, и результирующие методы с одинаковыми именами рассматриваются как совершенно разные.

2 часто используется в динамических языках (которые имеют тенденцию избегать перегрузки методов), так как возможно, что во время выполнения тип foo не имеет «обработчика» для сообщения с именем «Bar», разные языки обрабатывают это по-разному пути.

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

Наследование / повторное использование

или «Откуда берутся дети?»

  1. На основе классов
    • Реализации методов организованы в группы называется классы. Когда требуется наследование реализации, определяется класс, который расширяет родительский класс. Таким образом, он получает все раскрытые аспекты родительского (как поля, так и методы) и может изменить некоторые / все эти аспекты, но не может удалить любые. Вы можете добавлять и обновлять, но не удалять.
    • Примеры: C ++ / Java / C # (обратите внимание, что используют SmallTalk и Simula)
  2. На основе прототипов
    • Любой экземпляр объекта - это просто набор идентифицированных методов (обычно идентифицируемых по имени) и состояния в форме (снова именованных) полей. Всякий раз, когда требуется новый экземпляр этого типа, можно использовать существующий экземпляр для клонирования нового. Этот новый класс сохраняет копию состояния и методов предыдущего класса, но затем может быть изменен для удаления, добавления или изменения существующих именованных полей и методов.
    • Примеры: Self / JavaScript

Снова 1 имеет тенденцию происходить в статических языках, 2 в динамике, хотя это ни в коем случае не является требованием, они просто поддаются стилю.

Интерфейс или класс на основе

или «что или как?»

  1. Интерфейсы перечисляют требуемые методы. Это контракт
    • Примеры: VB6
  2. Методы списка классов, которые требуются, но могут при желании предоставить их реализацию
    • Примеры: Simula

Это очень не бинарный выбор. Большинство языков на основе классов допускают концепцию абстрактных методов (еще не реализованных). Если у вас есть класс, в котором все методы являются абстрактными (называемыми в C ++ чисто виртуальными), то этот класс в значительной степени представляет собой интерфейс, хотя и тот, который, возможно, также определил некоторое состояние (поля). Настоящий Интерфейс не должен иметь состояния (поскольку он определяет только , что возможно, а не как это происходит.

Только более старые языки ООП склонны полагаться исключительно на один или другой.
VB6 имеет только интерфейсы и не имеет наследования реализации.
Simula позволяет вам объявлять чисто виртуальные классы, но вы можете создавать их экземпляры (с использованием ошибок времени выполнения)

Single или Multiple Inheritance

или «Кто такой папа?»

  1. Одиночный
    • Только один тип может быть родительским для другого. В приведенной выше форме на основе классов вы можете расширить (взять реализация из) только одного типа. Обычно эта форма включает в себя концепцию интерфейсов как первоклассных аспектов языка, чтобы восполнить это.
    • Преимущества включают более чистые метаданные и самоанализ, более простые правила языка.
    • осложнения включают усложнение внедрения полезных методов в область действия (например, MixIns и методы расширения решить эту проблему)
    • Примеры: C # / java
  2. Несколько - вы можете расширять несколько классов
    • преимущества включают некоторые структуры легче моделировать и проектировать
    • . ​​Сложности включают сложные правила разрешения коллизий, особенно когда существуют перегруженные методы, которые могут принимать родительский тип.
    • Примеры: C ++ / Eiffel

Этот вопрос вызывает серьезные споры, тем более что он является ключевым отличием между реализацией ООП в C ++ и многими современными статически типизированными языками, которые воспринимаются как возможные преемники, такие как c # и java.

Изменчивость

или «что вы хотите со мной сделать?»

  1. Изменяемые
    • Объекты, однажды созданные, могут изменить свое состояние .
  2. Imutable
    • Однажды созданные объекты не могут быть изменены.

Зачастую это не все или ничего, это просто значение по умолчанию (наиболее часто используемые языки ООП по умолчанию изменяются по умолчанию). Это может оказать большое влияние на структуру языка. Многие в основном функциональные языки, включающие функции ООП, по умолчанию устанавливают неизменное состояние объектов.

«Чистота» их ООП

или «Является ли все объектом?»

  1. Абсолютно все в системе рассматривается как объект (возможно, даже вплоть до самих методов которые являются просто другим типом объекта и могут взаимодействовать так же, как и другие объекты).
    • Примеры: SmallTalk
  2. Не все является объектом, вы не можете передавать сообщения всем (хотя система может перепрыгивать через обручи, чтобы сделать это кажется, что вы можете)
    • Примеры: C ++ / C # / Java (см. примечание *)

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

  • В отношении Java / C # система autoboxing (или в c # ) позволяет обрабатывать, синтаксически любую переменную, как если бы это был объект, но на самом деле это не так, и это проявляется в таких областях, как попытка блокировки автоматически помещаемого объекта (отклонено компилятором, поскольку это будет явной ошибкой).

Статический или Динамический

или «Кем вы себя считаете?»

Гораздо более распространенный аспект языкового дизайна, и здесь не один, но присущий выбор на это решение влияют многие аспекты ООП, как упоминалось ранее.

Только аспекты полиморфного позднего связывания могут зависеть от:

  • Тип объекта, которому передается сообщение (во время компиляции / во время выполнения)
  • The тип параметра ( s ), который передается (во время компиляции / во время выполнения)

Чем динамичнее язык, тем более сложными становятся эти решения, но наоборот тем больше вводит пользователь языка, а не разработчик языка в решении. Давать примеры здесь было бы несколько глупо, поскольку статически типизированные языки могут быть модифицированы для включения динамических аспектов (например, c # 4.0).

64
ответ дан ShuggyCoUk 17 July 2009 в 15:25
поделиться

Eiffel - это статически типизированный, скомпилированный, с множественным наследованием чистый ООП язык.

http://dev.eiffel.com

4
ответ дан clemahieu 17 July 2009 в 15:25
поделиться

Я бы сказал, что ООП со статической и динамической типизацией - это две отдельные дисциплины в одной и той же школе ООП.

2
ответ дан Hooray Im Helping 17 July 2009 в 15:25
поделиться

Я поместил бы Java и C # в лагерь Simula:

  • Smalltalk, будучи динамически типизированным, довольно сильно отличается от четырех других языков, которые вы цитируете.

  • Smalltalk структурно типизирован (псевдоним утиной типизации), в то время как остальные четыре номинально типизированы.

(Что общего у Java и C # с Smalltalk, в основном основано на ВМ, но мало влияет на стиль программирования).

6
ответ дан AProgrammer 17 July 2009 в 15:25
поделиться

Из современных (и я использую термин слегка) ОО-языков программирования Objective C является наиболее похожим на smalltalk.

Сообщения:

В C ++, C # и Java: сообщения связаны во время компиляции.
Вы можете представить вызов метода как сообщение, отправляемое объекту.

В Цели C, Smalltalk: сообщения связаны во время выполнения.

3
ответ дан Martin York 17 July 2009 в 15:25
поделиться

Я бы сказал, что концептуально существует также довольно большое различие между ООП на основе классов (примерами которых являются Smalltalk, Simula, C # и Java) и ООП на основе прототипов (которая началась с Self и является наиболее распространенной). в JavaScript).

2
ответ дан Michael Borgwardt 17 July 2009 в 15:25
поделиться

Java и C # определенно не принадлежат к семейству Smalltalk. Алан Кей даже сказал, что когда он создавал ООП, он не имел в виду ничего подобного Java или C ++. Java, C # и C ++ интерпретируют ООП практически одинаково.

Такие языки, как Smalltalk и Ruby, имеют радикально отличную модель, основанную на передаче сообщений. В C ++ классы по сути являются пространствами имен для методов и состояний. Вызовы методов связаны во время компиляции. Smalltalk не связывает «вызов метода» до времени выполнения. Результатом этого является то, что в C ++

foo->bar

компилируется, чтобы означать «вызов метода bar для объекта foo». Если bar не является виртуальным, я бы предположил, что адрес метода bar специально указан.

В Smalltalk

foo bar

означает «отправить панель сообщений объекту foo». foo может делать с этим сообщением все, что захочет, когда оно придет. Поведение по умолчанию - вызывать метод с именем bar, но это не обязательно. Это свойство используется в Ruby для средств доступа к столбцам ActiveRecord. Когда у вас есть объект ActiveRecord, и вы отправляете ему имя столбца в его таблице базы данных в качестве сообщения, если нет метода с таким именем, он проверяет, есть ли столбец с этим именем в таблице, и если есть возвращает значение.

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

«Для меня ООП означает только обмен сообщениями, локальное хранение и защиту, а также скрытие процесса состояния и крайнюю позднюю привязку всех вещей. Это может быть сделано в Smalltalk и в LISP. Возможно, существуют другие системы, в которых это происходит. возможно, но я не знаю о них ". - Алан Кей, создатель Smalltalk

4
ответ дан Ben Hughes 17 July 2009 в 15:25
поделиться

Java, C # и C ++ следуют схожей стратегии ООП. Он основан на вызовах функций, которые связаны во время компиляции. В зависимости от его вызова, прямой вызов функции или смещение в vtable фиксируется, когда происходит компиляция. В отличие от ООП Smalltalk основан на передаче сообщений. Концептуально каждый вызов метода - это сообщение для принимающего объекта, спрашивающее, есть ли у него метод с именем «Foo».

Smalltalk не имеет понятия интерфейсов. У него есть только похожие методы. В группе языков C ++ все связано с интерфейсами. Нельзя реализовать AddRef и Release без реализации QueryInterface (даже если это просто заглушка), потому что все они являются частью интерфейса IUnknown. В Smalltalk нет IUnknown. Существует только набор из 3 функций, любая из которых может быть реализована или нет.

2
ответ дан Steve Rowe 17 July 2009 в 15:25
поделиться

Помимо вышеперечисленных пунктов, существует также концептуальная разбивка Smalltalk против Simula.

Концептуально «Smalltalk-style» обычно указывает, что метод, запускаемый при вызове сообщения, определяется во время выполнения, помогая полиморфизму.

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

В середине у нас есть Java: все методы виртуальные по умолчанию, но статически типизированы и имеют диспетчеризацию типа во время компиляции.

Пример:

// C++
class Base {
  void doSomething() {
    cout << "Base::doSomething() called!\n";
  }
}
class Derived : Base {
  void doSomething() {
     cout << "Derived::doSomething() called!\n";
  }
}
int main() {
  Base* b = new Base();
  Derived* d = new Derived();
  b->doSomething(); // prints "Base::doSomething() called!"
  d->doSomething(); // prints "Derived::doSomething() called!"
  Base* d2 = d;     // OK; Liskov substitution principle.
  d2->doSomething(); // prints "Base::doSomething called!"  (!)
  delete b;
  delete d;
  return 0;
}

VS:

// Objective-C
//Base.h
@interface Base
{
}
-(void)doSomething
@end
//Base.m
#import "Base.h"
@implementation Base
-(void) doSomething {
  printf("doSomething sent to Base!");
}
@end
//Derived.h
#import "Base.h"
#import "Base.m"
@interface Derived : Base
{
}
@end
//Derived.m
#import "Derived.h"
@implementation Derived
-(void) doSomething {
  printf("doSomething sent to Derived!")
}
@end

//Main.m
#import "Base.h"
#import "Base.m"
#import "Derived.h"
#import "Derived.m"
int main() {
  Base* b = [[Base alloc] init];
  Derived* d = [[Derived alloc] init];
  [b doSomething]; // prints "doSomething sent to Base!"
  [d doSomething]; // prints "doSomething sent to Derived!"
  Base* d2 = d;
  [d2 doSomething]; // prints "doSomething sent to Derived!"
  [b release];
  [d release];
  return 0;
}
1
ответ дан thkala 17 July 2009 в 15:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: