В чем разница между замыканиями и традиционными уроками? - PullRequest
8 голосов
/ 30 июля 2010

Каковы плюсы и минусы закрытия против классов и наоборот?

Edit: Как сказал пользователь Faisal, и замыкания, и классы могут использоваться для «описания сущности, которая поддерживает и манипулирует состоянием», поэтому замыкания обеспечивают способ программирования объектно-ориентированным способом с использованием функциональных языков. Как и большинство программистов, я больше знаком с классами.

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

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

Ответы [ 3 ]

9 голосов
/ 30 июля 2010

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

В C ++ замыкания не доступны синтаксически, поэтому вы вынуждены использовать «функторы», которые являются объектамиэто переопределение operator() и может быть вызвано способом, похожим на вызов функции.

В Java у вас даже нет функторов, поэтому вы получаете такие вещи, как шаблон Visitor, который был бы просто более высокимФункция заказа на языке, который поддерживает замыкания.

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

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

Лично я бы сказал, что в любом языке, который имеет синтаксис для обоих, замыкания являютсяБолее понятный и понятный способ выражения объектов одним методом.И наоборот, если ваше закрытие начинает обрабатывать диспетчеризацию для вложенных замыканий на основе входящих параметров, вы, вероятно, должны использовать объект вместо этого.

4 голосов
/ 30 июля 2010

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

Если вы хотите явно показать, что все ваши объекты имеют общее определениеи вы хотите строгую проверку типа такого, вы, вероятно, хотите использовать класс.Недостаток неспособности изменить структуру вашего класса во время выполнения - на самом деле сильная сторона в этом случае, поскольку вы точно знаете, с чем имеете дело.

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

2 голосов
/ 30 июля 2010

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

Например, посмотрите на следующий код C #:

static void Main(String[] args)
{
    int i = 4;
    var myDelegate = delegate()
    {
        i = 5;
    }

    Console.WriteLine(i);
    myDelegate();
    Console.WriteLine(i);
}

Это дает «4», а затем «5».myDelegate, будучи делегатом, является замыканием и знает обо всех переменных, используемых в настоящее время функцией.Поэтому, когда я вызываю его, разрешается изменять значение i внутри родительской функции.Это не будет разрешено для нормальной функции.

Классы, если вы знаете, что они собой представляют, совершенно разные.

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

class MainClosure()
{
    public int i;

    void Apply()
    {
        i = 5;
    }
}

static void Main(String[] args)
{
    MainClosure closure;
    closure.i = 4;

    Console.WriteLine(closure.i);
    closure.Apply();
    Console.WriteLine(closure.i);
}

Мы преобразовали delegate в класс, который мы назвали MainClosure.Вместо создания переменной i внутри функции Main мы создали объект MainClosure с полем i.Это тот, который мы будем использовать.Кроме того, мы создали код, который функция выполняет внутри метода экземпляра, а не внутри метода.

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

...