Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Language agnostic 闭包在OOP中有什么用途?_Language Agnostic_Oop_Functional Programming - Fatal编程技术网

Language agnostic 闭包在OOP中有什么用途?

Language agnostic 闭包在OOP中有什么用途?,language-agnostic,oop,functional-programming,Language Agnostic,Oop,Functional Programming,PHP和.Net有闭包;我一直在想,在OOP和设计模式中使用闭包的例子有哪些,以及它们与纯OOP编程相比有哪些优势 作为澄清,这不是OOP与函数式编程,而是如何在OOP设计中最好地使用闭包。闭包如何适应工厂或观察者模式?例如,您可以使用哪些技巧来澄清设计并导致松散耦合。闭包对于事件处理非常有用。这个例子有点做作,但我认为它传达了一个想法: class FileOpener { public FileOpener(OpenFileTrigger trigger) {

PHP和.Net有闭包;我一直在想,在OOP和设计模式中使用闭包的例子有哪些,以及它们与纯OOP编程相比有哪些优势


作为澄清,这不是OOP与函数式编程,而是如何在OOP设计中最好地使用闭包。闭包如何适应工厂或观察者模式?例如,您可以使用哪些技巧来澄清设计并导致松散耦合。

闭包对于事件处理非常有用。这个例子有点做作,但我认为它传达了一个想法:

class FileOpener
{
     public FileOpener(OpenFileTrigger trigger)
     {
         trigger.FileOpenTriggered += (sender, args) => { this.Open(args.PathToFile); };
     }

     public void Open(string pathToFile) 
     { 
         //… 
     }
}

my file opener可以通过直接调用
instance.open(pathToFile)
打开文件,也可以由某个事件触发。如果我没有匿名函数+闭包,我就必须编写一个方法,该方法除了响应此事件之外没有其他用途。

假设您希望提供一个能够创建任意数量的
FileOpener
实例的类,但要遵循IoC原则,您不希望创建
FileOpener
s的类实际知道如何操作(换句话说,您不希望
new
s)。相反,您希望使用依赖项注入。但是,您只希望此类能够生成
FileOpener
实例,而不仅仅是任何实例。以下是您可以做的:

class AppSetup
{
    private IContainer BuildDiContainer()
    {
         // assume this builds a dependency injection container and registers the types you want to create
    }


    public void setup()
    {
        IContainer container = BuilDiContainer();
        // create a function that uses the dependency injection container to create a `FileOpener` instance
        Func<FileOpener> getFileOpener = () => { return container.Resolve<FileOpener>(); };

        DependsOnFileOpener dofo = new DependsOnFileOpener(getFileOpener);

    }
}
类AppSetup
{
私有IContainer BuildinContainer()
{
//假设这构建了一个依赖项注入容器,并注册了您想要创建的类型
}
公共作废设置()
{
IContainer容器=BuilDiContainer();
//创建一个使用依赖项注入容器创建“FileOpener”实例的函数
Func getFileOpener=()=>{return container.Resolve();};
DependsOnFileOpener dofo=新的DependsOnFileOpener(getFileOpener);
}
}
现在,您的类需要能够生成FileOpener实例。您可以使用依赖项注入为其提供此功能,同时保持松散耦合

class DependsOnFileOpener()
{
    public DependesOnFileOpener(Func<FileOpener> getFileOpener)
    {
        // this class can create FileOpener instances any time it wants, without knowing where they come from
        FileOpener f = getFileOpener();
    }
}
class DependsOnFileOpener()
{
public DependesOnFileOpener(Func getFileOpener)
{
//此类可以随时创建FileOpener实例,而不知道它们来自何处
FileOpener f=getFileOpener();
}
}

任何具有闭包的语言都可以使用闭包进行蹦床,这是一种将递归重构为迭代的技术。这可以让您摆脱许多算法的幼稚实现遇到的“堆栈溢出”问题

蹦床是将闭包“反弹”回调用方的函数。闭包捕获了“剩余的工作”

例如,在Python中,可以定义递归累加器来对数组中的值求和:

testdata = range(0, 1000)
def accum(items):
        if len(items) == 0:
                return 0
        elif len(items) == 1:
                return items[0]
        else:
                return items[0] + accum(items[1:])

print "will blow up:", accum(testdata)
在我的机器上,当项目长度超过998时,这会导致堆栈溢出

同样的功能可以在蹦床式中使用闭包完成:

def accum2(items):
        bounced = trampoline(items, 0)
        while (callable(bounced)):
                bounced = bounced()
        return bounced

def trampoline(items, initval):
        if len(items) == 0:
                return initval
        else:
                return lambda: trampoline(items[1:], initval+items[0])

通过将递归转换为迭代,您不会破坏堆栈。闭包的特性是捕获计算本身的状态,而不是像递归那样捕获堆栈上的状态

这可能是社区维基。我也在想同样的事情。这个页面:有一个例子,但它可以很容易地重写没有闭包。巧妙的技巧!我想我以前从未见过这种情况。它在Python中最常见吗(这可以解释为什么我从未见过它)?它在Lisp世界中非常常见。在大多数Lisp实现中,它实际上是由编译器自动完成的(“尾部调用优化”)。但有时你必须手工操作,因为编译器只能识别特定配置中的模式。这在命令式语言中并不常见,但例如LEPL()使用蹦床来防止复杂的递归解析器溢出堆栈。