如何在Swift中创buildgenerics协议?

我想创build一个方法,采用通用input并返回一个通用的值的协议。

这是我到目前为止所尝试的,但它会产生语法错误。

使用未声明的标识符T.

我究竟做错了什么?

protocol ApiMapperProtocol { func MapFromSource(T) -> U } class UserMapper: NSObject, ApiMapperProtocol { func MapFromSource(data: NSDictionary) -> UserModel { var user = UserModel() as UserModel var accountsData:NSArray = data["Accounts"] as NSArray return user } } 

协议有点不同。 查看苹果文档中的“关联types”。

这是你在你的例子中使用它的方式

 protocol ApiMapperProtocol { associatedtype T associatedtype U func MapFromSource(T) -> U } class UserMapper: NSObject, ApiMapperProtocol { typealias T = NSDictionary typealias U = UserModel func MapFromSource(data:NSDictionary) -> UserModel { var user = UserModel() var accountsData:NSArray = data["Accounts"] as NSArray // For Swift 1.2, you need this line instead // var accountsData:NSArray = data["Accounts"] as! NSArray return user } } 

为了详细解释Lou Franco的回答 ,如果你想创build一个使用特定的ApiMapperProtocol的方法,你可以这样做:

 protocol ApiMapperProtocol { associatedtype T associatedtype U func MapFromSource(T) -> U } class UserMapper: NSObject, ApiMapperProtocol { // these typealiases aren't required, but I'm including them for clarity // Normally, you just allow swift to infer them typealias T = NSDictionary typealias U = UserModel func MapFromSource(data:NSDictionary) -> UserModel { var user = UserModel() var accountsData:NSArray = data["Accounts"] as NSArray // For Swift 1.2, you need this line instead // var accountsData:NSArray = data["Accounts"] as! NSArray return user } } class UsesApiMapperProtocol { func usesApiMapperProtocol< SourceType, MappedType, ApiMapperProtocolType: ApiMapperProtocol where ApiMapperProtocolType.T == SourceType, ApiMapperProtocolType.U == MappedType>( apiMapperProtocol: ApiMapperProtocolType, source: SourceType) -> MappedType { return apiMapperProtocol.MapFromSource(source) } } 

UsesApiMapperProtocol现在保证只接受与给定ApiMapperProtocol兼容的SourceType

 let dictionary: NSDictionary = ... let uses = UsesApiMapperProtocol() let userModel: UserModel = uses.usesApiMapperProtocol(UserMapper() source: dictionary) 

您可以使用types擦除模板方法…

 protocol HeavyDelegate : class { func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R } class Heavy<P, R> { typealias Param = P typealias Return = R weak var delegate : HeavyDelegate? func inject(p : P) -> R? { if delegate != nil { return delegate?.heavy(self, shouldReturn: p) } return nil } func callMe(r : Return) { } } class Delegate : HeavyDelegate { typealias H = Heavy<(Int, String), String> func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R { let h = heavy as! H h.callMe("Hello") print("Invoked") return "Hello" as! R } } let heavy = Heavy<(Int, String), String>() let delegate = Delegate() heavy.delegate = delegate heavy.inject((5, "alive"))