关闭类的闭包有哪些优缺点,反之亦然?
编辑: 正如用户Faisal所说,闭包和类都可以用来“描述维护和操作状态的实体”,因此闭包提供了一种使用函数语言以面向对象的方式编程的方法。像大多数程序员一样,我对类更熟悉。
这个问题的目的不是打开另一场关于编程范式更好的火焰战争,或者封闭和阶级是完全等同的,还是穷人的另一个。
我想知道的是,如果有人发现一种情况,一种方法真的胜过另一种,以及为什么。
答案 0 :(得分:9)
在功能上,闭包和对象是等效的。闭包可以模拟对象,反之亦然。所以你使用哪一个是语法方便的问题,或者你的编程语言最能处理的问题。
在C ++中,闭包在语法上是不可用的,所以你不得不使用“functor”,它们是覆盖operator()
的对象,可以以看起来像函数调用的方式调用。
在Java中,你甚至没有仿函数,所以你会得到像访问者模式这样的东西,它只是支持闭包的语言中的高阶函数。
在标准Scheme中你没有对象,所以有时候你最终会通过编写带有调度函数的闭包来实现它们,根据传入的参数执行不同的子闭包。
在像Python这样的语言中,其语法包含仿函数和闭包,它基本上是一种品味问题,你觉得这是表达你所做事情的更好方式。
就我个人而言,我会说,在任何具有两种语法的语言中,闭包都是一种使用单一方法表达对象的更清晰,更清晰的方式。反之亦然,如果你的闭包开始根据传入的参数处理调度到子闭包,你可能应该使用一个对象。
答案 1 :(得分:4)
就我个人而言,我认为这是一个使用正确工具的问题......更具体地说,就是正确传达你的意图。
如果要明确显示所有对象共享一个公共定义并希望对其进行强类型检查,则可能需要使用类。在这种情况下,无法在运行时改变类结构的缺点实际上是一种优势,因为您确切知道您正在处理的是什么。
如果您想要创建一个异构的“对象”集合(即状态表示为在某些函数内部关闭的变量以及内部函数来操作该数据),您最好创建一个闭包。在这种情况下,对于您最终得到的对象的结构没有真正的保证,但您可以灵活地在运行时完全按照您的喜好定义它。
实际上,谢谢你的要求;我回应了一些下意识的“课程和闭包完全不同!”最初的态度,但通过一些研究,我发现这个问题并不像我想的那样干脆。
答案 2 :(得分:2)
闭包与类非常相关。类允许您定义字段和方法,并且闭包从函数调用中保存有关局部变量的信息。没有可能以语言无关的方式比较两者:它们完全没有用于同一目的。此外,闭包与函数式编程比与面向对象编程更相关。
例如,查看以下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
字段。这是我们将使用的那个。此外,我们已经构建了函数在实例方法中执行的代码,而不是在方法内部。
正如您所看到的,尽管这是一个简单的例子(只有一个变量),但它的工作要多得多。在您需要闭包的上下文中,使用对象是一个糟糕的解决方案。但是,类不仅对创建闭包有用,而且它们的通常目的通常也大不相同。