Swift-使func类型显式(在协议中)

时间:2018-09-19 12:30:28

标签: swift function closures

假设我们有一个像typealias这样的协议:

// common closure types
typealias Action = () -> Void
typealias Consumer<T> = (T) -> Void

// here starts the fun
typealias AsyncAction = (Action?) -> Void
typealias AsyncGetter<T> = (Consumer<T>?) -> Void
typealias AsyncSetter<T> = (T, Action?) -> Void

// make compiler and you happy
typealias Foo = Void
typealias Bar = Void

protocol FooBarDatabaseAccess {
    func doSomething()
    func doSomethingAsync(completion: Action?)//: AsyncAction
    func getFooAsync(completion: Consumer<Foo>?)//: AsyncGetter<Foo>
    func getBarAsync(completion: Consumer<Bar>?)//: AsyncGetter<Bar>
    func setBarAsync(value: Bar, completion: Action?)//: AsyncSetter<Bar>
}


我想指定类似于let / var声明的函数类型,并在其后加上可分配的类型:

/* -- let/var -- */

// implicitly typed as String, determined from initial assignment
let implicitString = ""

// explicitly typed as String, though initialisation is omitted here
let explicitString: String


/* -- func -- */

// implicitly typed as () -> Void, determined from argument/return type(s)
func implicitAction()

// explicitly typed as Action, compiler should complain if it does not conform to the type (alias)
???


我该如何实现?

可能的解决方法是将其转换为属性声明,但这很令人困惑:

var explicitAction: Action = { get }

1 个答案:

答案 0 :(得分:4)

由于Actiontypealias而不是类型,因此swift无法区分它们。

documentation中所述:

  

声明类型别名后,可以在程序中的任何地方使用别名代替现有类型。现有类型可以是命名类型或复合类型。类型别名不会创建新类型。他们只是允许名称引用现有类型。

编辑:不好意思,我认为您想区分() -> VoidAction。 据我所知,使用闭包是快速完成此操作的唯一方法。

typealias Foo = (Int) -> Void

protocol FooBar {
  var foo: Foo { get }
}

class FooBarBaz: FooBar {
  var foo: Foo = { intValue in
    // ...
  }
}

编辑2:其他信息:

根据Grammar of a function declaration,声明功能的唯一方法是显式提供parameter-clause,这需要在括号之间列出所有参数:

  

函数声明→函数头函数名称泛型子句 opt 函数签名泛型子句 opt 函数-body opt

     

功能签名→参数子句抛出 opt function-result opt

     

参数子句→()| (参数列表)

因此,显然,如果不使用闭包,就无法将类型声明为签名的函数。