Swift中的引用类型 - 对函数/闭包的引用

时间:2015-01-30 17:14:50

标签: xcode swift reference reference-type

我注意到在Swift中,当我使用返回值 returnValue 创建 originalFunction(),并创建一个新函数时,让referenceA = originalFunction() ,这将会发生:

  1. 因为 referenceA 是对 originalFunction()的引用,当我让referenceB = referenceA 时, referenceB referenceA 将分享 returnValue
  2. 但当我让referenceC = originalFunction()时,在这种情况下,我认为 referenceC referenceA 也应该共享 returnValue 因为它们都引用 originalFunction(),所以不是这样。
  3. 为什么?

    示例:

    func makeIncrementor(forIncrement amount:Int) -> () -> Int {    
        var runningTotal = 0     
        func incrementor() -> Int {    
            runningTotal += amount    
            return runningTotal    
        }    
        return incrementor    
    }    
    
    //then let's make referenceA    
    
    let incrementByTen = makeIncrementor(forIncrement:10)    
    incrementByTen()    
    //returns 10    
    incrementByTen()    
    //returns 20    
    
    //Now make referenceB    
    let incrementBy10 = incrementByTen    
    //referenceA and referenceB will share the *returnValue*:    
    incrementBy10()    
    //returns 30    
    
    //Now make referenceC    
    let incrementByTen10 = makeIncrementor(forIncrement:10)    
    //referenceA and referenceC do not share the *returnValue*    
    incrementByTen10()    
    //returns 10    
    

2 个答案:

答案 0 :(得分:3)

您的makeIncrementor函数会创建一个新的() -> Int递增函数,用于捕获您在其上方创建的runningTotal变量。因为当您将incrementByTen闭包分配给新的incrementBy10闭包时,闭包是reference types,您实际上只是分配一个引用,并且这些var中的每一个都指向相同的闭包,所以调用其中任何一个都会增加闭包捕获的runningTotal var

当您再次拨打makeIncrementor时,会创建一个关闭,以捕获新的runningTotal var,因此它不会共享runningTotal incrementor {1}}使用您创建的第一个闭包。

您的func makeIncrementor未被共享,因为您在makeIncrementor内声明了它,因此它仅对func的调用范围有效并且将被重新声明在下次makeIncrementor被调用时作为新的makeIncrementor。如果您希望每次调用incrementor时都要共享此内容,则需要在func之外声明makeIncrementor private String executeCommand(String command) { StringBuffer output = new StringBuffer(); Process p; try { p = Runtime.getRuntime().exec(command); p.waitFor(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = ""; while ((line = reader.readLine())!= null) { output.append(line + "\n"); } } catch (Exception e) { e.printStackTrace(); } return output.toString(); }

答案 1 :(得分:0)

如果我的理解是正确的,这是因为嵌套函数仅仅是创建闭包的语法糖,因此每次调用incrementor时都会创建另一个makeIncrementor实例。

上面的代码几乎与此相同。

func makeIncrementor(forIncrement amount:Int) -> () -> Int {    
    var runningTotal = 0     
    let incrementor = {    
        runningTotal += amount    
        return runningTotal    
    }    
    return incrementor    
}