我想创建一个带有通用输入并返回通用值的方法的协议。
这是我到目前为止所尝试的,但它会产生语法错误。
使用未声明的标识符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
}
}
答案 0 :(得分:129)
协议有点不同。查看“关联类型”in Apple's documentation。
这是您在示例中使用它的方式
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
}
}
答案 1 :(得分:20)
稍微阐述Lou Franco's answer,如果你想创建一个使用特定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
现在保证只接受与给定SourceType
兼容的ApiMapperProtocol
:
let dictionary: NSDictionary = ...
let uses = UsesApiMapperProtocol()
let userModel: UserModel = uses.usesApiMapperProtocol(UserMapper()
source: dictionary)
答案 2 :(得分:2)
为了获得泛型并像这样let userMapper: ApiMapperProtocol = UserMapper()
进行声明,您必须具有符合返回泛型元素的协议的泛型类。
protocol ApiMapperProtocol {
associatedtype I
associatedType O
func MapFromSource(data: I) -> O
}
class ApiMapper<I, O>: ApiMapperProtocol {
func MapFromSource(data: I) -> O {
fatalError() // Should be always overridden by the class
}
}
class UserMapper: NSObject, ApiMapper<NSDictionary, UserModel> {
override func MapFromSource(data: NSDictionary) -> UserModel {
var user = UserModel() as UserModel
var accountsData:NSArray = data["Accounts"] as NSArray
return user
}
}
现在,您也可以将userMapper
称为ApiMapper
,它对UserMapper
有特定的实现:
let userMapper: ApiMapper = UserMapper()
let userModel: UserModel = userMapper.MapFromSource(data: ...)
答案 3 :(得分:-1)
如何创建和使用通用协议
通用协议{
associatedtype T
associatedtype U
func operation(_ t:T)->U
}
//使用通用协议
结构测试:通用{
typealias T = UserModel
typealias U = Any
func operation(_ t: UserModel)->Any {
let dict = ["name":"saurabh"]
return dict
}
}