swift:将函数类型赋给变量

时间:2017-10-05 16:23:34

标签: swift function types

    struct System {
        var method: (() -> ())?
        var curMethod: Int

        init() {
            method = nil
curMethod = 0
        }

        mutating func method1() {
            curMethod = 1
        }

        mutating func method2() {
            curMethod = 2
        }
    }

    var sys = System()
    sys.method = System.method1
    sys.method!()

我收到错误,无法指定类型(inout System) -> () -> ()' to type '(() -> ())?的值。我做错了什么?

2 个答案:

答案 0 :(得分:1)

首先,您的行sys.method = System.method1是错误的,因为它需要method1作为静态函数(如类函数)而不是实例函数,因此应将其更改为{ {1}}。但这是不允许的 - 错误是“错误:不允许部分应用'变异'方法”。

如果您将sys.method = sys.method1作为一个类(而不是结构),那么如果您将System替换为System.method1,它将会起作用。

这样做的原因是sys.method1实际上比一个简单的函数要多得多 - 它是一个curried函数(用编译器生成的函数计算),它有效地创建了一个新的副本具有“新”值的struct - 因此,您A)无法直接访问它(“不允许部分应用程序”)和B)您无法将其分配给mutating func变量。

答案 1 :(得分:0)

因此,参与者提出了3种变体。一切正常,使用类而不是结构对我来说似乎不那么复杂。

struct System1 {

    var method: (() -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    mutating func method1() { curMethod = 1 }
    mutating func method2() { curMethod = 2 }

}

struct System2 {

    var method: ((inout System2) -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    mutating func callCurrentMethod() { method?(&self) }
    mutating func method1() { curMethod = 1 }
    mutating func method2() { curMethod = 2 }

}

class System3 {

    var method: (() -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    func method1() { curMethod = 1 }
    func method2() { curMethod = 2 }

}

var struct1 = System1()
var struct2 = System2()
var class1 = System3()

print(struct1.curMethod)
let curried = System1.method1
let unsafe = curried(&struct1)
unsafe()
print(struct1.curMethod)

print(struct2.curMethod)
struct2.method = { $0.method1() }
struct2.callCurrentMethod()
print(struct2.curMethod)

print(class1.curMethod)
class1.method = class1.method1
class1.method!()
print(class1.curMethod)