Каково различие между закрытиями и традиционными классами?

Каковы за и против закрытий против классов, и наоборот?

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

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

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

9
задан Sebastián Grignoli 30 July 2010 в 07:51
поделиться

3 ответа

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

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

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

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

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

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

11
ответ дан 4 December 2019 в 12:15
поделиться

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

Например, посмотрите на следующий код 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 inside "родительской" функции. Для обычной функции это было бы недопустимо.

Классы, если вы знаете, что это такое, - это совершенно другое.

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

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);
}

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

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

2
ответ дан 4 December 2019 в 12:15
поделиться

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

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

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

Спасибо за вопрос, на самом деле; сначала я ответил что-то вроде "классы и закрытия - это совершенно разные вещи!", но после некоторых исследований я понял, что проблема не так однозначна, как я думал.

4
ответ дан 4 December 2019 в 12:15
поделиться
Другие вопросы по тегам:

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