符合协议的类作为Swift中的函数参数

Mar*_*don 88 swift

在Objective-C中,可以将符合协议的类指定为方法参数.例如,我可以有一个只允许UIViewController符合的方法UITableViewDataSource:

- (void)foo:(UIViewController<UITableViewDataSource> *)vc;
Run Code Online (Sandbox Code Playgroud)

我无法在Swift中找到一种方法(也许它还不可能).您可以使用指定多个协议func foo(obj: protocol<P1, P2>),但是如何要求对象也是特定类?

Nat*_*ook 128

您可以将其定义foo为泛型函数,并使用类型约束来同时要求类和协议.

斯威夫特4

func foo<T: UIViewController & UITableViewDataSource>(vc: T) {
    .....
}
Run Code Online (Sandbox Code Playgroud)

Swift 3(也适用于Swift 4)

func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource { 
    ....
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特2

func foo<T: UIViewController where T: UITableViewDataSource>(vc: T) {
    // access UIViewController property
    let view = vc.view
    // call UITableViewDataSource method
    let sections = vc.numberOfSectionsInTableView?(tableView)
}
Run Code Online (Sandbox Code Playgroud)

  • 在Swift 3中,这似乎在Xcode 8 beta 6中被弃用,优先选择:`func foo <T:UIViewController>(vc:T)其中T:UITableViewDataSource {...}` (11认同)
  • 我认为这是必要的,这有点不幸.希望将来会有一个更清晰的语法,比如`protocol <>`提供(但`protocol <>`不能包含非协议类型). (3认同)

Jer*_*ker 27

在Swift 4中,您可以通过新的&sign来实现:

let vc: UIViewController & UITableViewDataSource
Run Code Online (Sandbox Code Playgroud)


Jon*_*ros 17

Swift书籍文档建议您使用带有where子句的类型约束:

func someFunction<C1: SomeClass where C1:SomeProtocol>(inParam: C1) {}
Run Code Online (Sandbox Code Playgroud)

这保证了"inParam"类型为"SomeClass",其条件是它也遵守"SomeProtocol".您甚至可以指定由逗号分隔的多个where子句:

func itemsMatch<C1: SomeProtocol, C2: SomeProtocol where C1.ItemType == C2.ItemType,    C1.ItemType: SomeOtherProtocol>(foo: C1, bar: C2) -> Bool { return true }
Run Code Online (Sandbox Code Playgroud)


小智 5

斯威夫特5:

func foo(vc: UIViewController & UITableViewDataSource) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

所以本质上就是Jeroen上面的回答。