如何在Swift闭包中摆脱$ 0?

时间:2015-05-31 18:24:25

标签: swift

假设我有一个班级:

class Test {
    func someMethod() {}

    init(closure:(Test)->Void) {
        closure(self)
    }
}

我可以在另一个类(1)

的另一个方法中调用init
Test {
    $0.someMethod()
}

或像这样(2)

Test { t in
    t.someMethod()
}

是否有任何可能的解决方案可以在没有“$ 0”或“t”的情况下编写完全相同的内容?我想得到这段代码(3)

Test {
    someMethod()
}

行为必须与(1)或(2)完全相同。

有可能吗?也许不是关闭,而是使用其他一些Swift功能?

我想做类似Kotlin类型安全构建器的事情:http://kotlinlang.org/docs/reference/type-safe-builders.html

3 个答案:

答案 0 :(得分:1)

不确定你追求的是什么,但我想知道这一点点伏都教对你有用:

    class Test {
        var name : String
        init(_ name:String) {self.name = name}
        func someMethod() { println("Hi, my name is \(name)") }
    }
    let f = Test.someMethod
    let t1 = Test("matt")
    let t2 = Test("bealex")
    f(t1)() // Hi, my name is matt
    f(t2)() // Hi, my name is bealex

要点是f(t1)本身就是一个函数,在调用时,会将someMethod发送到实例t1。你可能会从中获得一些好处。

答案 1 :(得分:1)

我相信在Swift中这是不可能的,因为swift缺少某种动态扩展功能功能。

在swift中,扩展的唯一方法是定义一个新函数(或其他),如:

extension Type {
  func function() {}
}

据我所知,没有可能动态定义扩展。

所以我们真正缺少的是这样的:(下一版Swift的愿望清单?)

以下代码不起作用,示例如何使用

class Test {
    var aVar = 0
    func someMethod() {}

    // Param declares function as an extension on type Test!
    class func initialize(closure: Test.()->Void) -> Test {
        let instance = Test()
        instance.closure() 
        return instance
    }
} 

// And it would be possible to do:
Test.initialize {
    self.someMethod()
    aVar = 1234 // With or without self, with or without self...
}

再次,不工作。但是哦,它会有多好......

更新:代码现在有点固定。

答案 2 :(得分:0)

您必须满足类型检查器。所以typechecker希望你写一个Test -> Void的闭包。如果您不使用Test参数,则可以忽略它:

Test { _ in someAnotherMethod() }

编辑:我完全误解了你的问题@bealex。现在我有另一个解决方案,但它很难看,它有一些局限性。这是代码

class Test {

    init (_ f: Test -> () -> Void) {
        f(self)()
    }

    func doSomething() {
        println("Hello world")
    }
}

let test = Test(Test.doSomething)

这仅适用于不采用(或更确切地说void)参数的方法。有关如何工作:Swift实例方法是curried函数,第一个参数是selfLink

例如,采用一个参数的方法,我们可以编写交换方法来交换函数的参数顺序。

func swap<A, B, C>(f: A -> B -> C) -> B -> A -> C {
    return { b in { a in f(a)(b)} }
}

现在我们可以写

class Test {

    init (_ f: Test -> Void) {
        f(self)
    }

    func doSomethingWithNumber(number: Int, str: String) {
        println("Hello planet \(number), \(str)")
    }
}


let test = Test(swap(Test.doSomethingWithNumber)(10, "Greetings"))

但这比使用普通$0 and $1更加冗长。无论如何,这是另一种观点。