"Закрытие - это плохие человеческие объекты и наоборот". Что это значит?
Закрытие - это плохие человеческие объекты и наоборот.
Я видел это утверждение в many места в Интернете (включая SO), но я не совсем понимаю, что это значит. Может кто-нибудь объяснить, что это значит?
Если возможно, укажите примеры в своем ответе.
Ответы
Ответ 1
Объекты - это плохие замыкания человека.
Рассмотрим Java. Java - это объектно-ориентированный язык программирования без поддержки языкового уровня для реальных лексических замыканий. Как программисты Java используют анонимные внутренние классы, которые могут закрывать переменные, доступные в лексической области (при условии, что они final
). В этом смысле объекты - это плохие замыкания человека.
Закрытие - это плохие человеческие объекты.
Рассмотрим Haskell. Haskell - это функциональный язык без поддержки уровня языка для реальных объектов. Однако они могут быть смоделированы с использованием закрытий, как описано в этой отличной статье Олега Киселева и Ральфа Ламмеля. В этом смысле закрытие - это плохие человеческие объекты.
Если вы исходите из фона OO, вы, вероятно, найдете мышление с точки зрения объектов более естественным, и поэтому можете думать о них как о более фундаментальной концепции, чем о закрытии. Если вы исходите из фона FP, вы можете найти мышление с точки зрения более естественных замыканий и, следовательно, подумать о них как о более фундаментальной концепции, чем о объектах.
Мораль истории состоит в том, что замыкания и объекты - это идеи, которые выражаются друг с другом, и ни одна из них не является более фундаментальной, чем другая. Это все, что касается рассматриваемого заявления.
В философии это называется реализацией, зависящей от модели.
Ответ 2
Дело в том, что замыкания и объекты выполняют одну и ту же цель: инкапсуляция данных и/или функциональных возможностей в единую логическую единицу.
Например, вы можете создать класс Python, который представляет такую собаку:
class Dog(object):
def __init__(self):
self.breed = "Beagle"
self.height = 12
self.weight = 15
self.age = 1
def feed(self, amount):
self.weight += amount / 5.0
def grow(self):
self.weight += 2
self.height += .25
def bark(self):
print "Bark!"
И затем я создаю экземпляр класса как объект
>>> Shaggy = Dog()
Объект Shaggy имеет встроенные данные и функциональные возможности. Когда я звоню Shaggy.feed(5)
, он получает фунт. Этот фунт хранится в переменной, которая хранится как атрибут объекта, который более или менее означает, что он находится во внутренней области объектов.
Если бы я кодировал некоторый Javascript, я бы сделал нечто подобное:
var Shaggy = function() {
var breed = "Beagle";
var height = 12;
var weight = 15;
var age = 1;
return {
feed : function(){
weight += amount / 5.0;
},
grow : function(){
weight += 2;
height += .25;
},
bark : function(){
window.alert("Bark!");
},
stats : function(){
window.alert(breed "," height "," weight "," age);
}
}
}();
Здесь вместо создания области внутри объекта я создал область внутри функции, а затем вызвал эту функцию. Функция возвращает объект JavaScript, состоящий из некоторых функций. Поскольку эти функции получают доступ к данным, которые были выделены в локальной области, память не восстанавливается, что позволяет вам продолжать использовать их через интерфейс, предоставляемый закрытием.
Ответ 3
Объект, в его самом простом виде, представляет собой просто набор состояний и функций, которые работают в этом состоянии. Закрытие также представляет собой совокупность состояний и функцию, которая работает в этом состоянии.
Скажем, я вызываю функцию, которая выполняет обратный вызов. В этом обратном вызове мне нужно оперировать некоторым состоянием, известным перед вызовом функции. Я могу создать объект, который воплощает это состояние ( "поля" ) и содержит функцию-член ( "метод" ), которая выполняет функцию обратного вызова. Или, я мог бы взять быстрый и легкий ( "бедный человек" ) маршрут и создать закрытие.
Как объект:
class CallbackState{
object state;
public CallbackState(object state){this.state = state;}
public void Callback(){
// do something with state
}
}
void Foo(){
object state = GenerateState();
CallbackState callback = new CallbackState(state);
PerformOperation(callback.Callback);
}
Это псевдо-С#, но по-другому аналогично другим языкам OO. Как вы можете видеть, существует достаточное количество шаблонов, связанных с классом обратного вызова для управления состоянием. Это было бы намного проще с помощью закрытия:
void Foo(){
object state = GenerateState();
PerformOperation(()=>{/*do something with state*/});
}
Это лямбда (опять же, в синтаксисе С#, но концепция похожа на другие языки, поддерживающие закрытие), которая дает нам все возможности класса без необходимости писать, использовать и поддерживать отдельный класс.
Вы также услышите следствие: "объекты - это бедные люди". Если я не могу или не буду использовать закрытие, то я вынужден выполнять свою работу с использованием объектов, как в моем первом примере. Хотя объекты обеспечивают большую функциональность, закрытие часто является лучшим выбором, когда закрытие будет работать по причинам, уже заявленным.
Следовательно, бедный человек без предметов может часто выполнять работу с закрытием, а бедный человек без закрытия может выполнить свою работу с использованием объектов. Богатый человек имеет и то, и другое использует для каждого задания правильный.
Ответ 4
EDITED: название вопроса не включает "наоборот", поэтому я постараюсь не предполагать намерения афера.
Два общих лагеря являются функциональными и императивными языками. Оба являются инструментами, которые могут выполнять аналогичные задачи по-разному с различными проблемами.
Закрытие - это плохие человеческие объекты.
Объекты - это плохие замыкания человека.
Индивидуально, каждое утверждение обычно означает, что у автора есть некоторый уклон, так или иначе, как правило, укорененный в их комфорте с одним языком или классом языка и дискомфортом с другим. Если это не смещение, они могут быть ограничены одной средой или другой. Авторы, которых я читал, говорят, что такие вещи обычно являются фанатиками-фанатиками, пуристами или языками. Я избегаю религиозных типов языка, если это возможно.
Закрытие - это плохие человеческие объекты. Объекты - плохие замыкания человека.
Автор этого "прагматика", а также довольно умный. Это означает, что автор ценит обе точки зрения и ценит, что они концептуально одно и то же. Это мой товарищ.
Ответ 5
"Объекты - закрытые люди" - это не просто утверждение некоторой теоретической эквивалентности - это общая идиома Java. Очень часто используют анонимные классы для завершения функции, которая фиксирует текущее состояние. Вот как это используется:
public void foo() {
final String message = "Hey ma, I'm closed over!";
SwingUtilities.invokeLater(new Runnable() {
public void run() {
System.out.println(message);
}
});
}
Это даже очень похоже на эквивалентный код, используя закрытие на другом языке. Например, использование Objective-C блоков (поскольку Objective-C достаточно похож на Java):
void foo() {
NSString *message = @"Hey ma, I'm closed over!";
[[NSOperationQueue currentQueue] addOperationWithBlock:^{
printf("%s\n", [message UTF8String]);
}];
}
Единственное реальное отличие заключается в том, что функциональность завершена в экземпляре анонимного класса new Runnable()
в версии Java.
Ответ 6
Просто так много сахара, поскольку закрытие скрывает анонимные объекты под юбками.