Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Swift中创建通用协议?_Swift - Fatal编程技术网

如何在Swift中创建通用协议?

如何在Swift中创建通用协议?,swift,Swift,我想用一个方法创建一个协议,该方法接受一个泛型输入并返回一个泛型值 这是我到目前为止尝试过的,但它会产生语法错误 使用未声明的标识符T 我做错了什么 protocol ApiMapperProtocol { func MapFromSource(T) -> U } class UserMapper: NSObject, ApiMapperProtocol { func MapFromSource(data: NSDictionary) -> UserModel {

我想用一个方法创建一个协议,该方法接受一个泛型输入并返回一个泛型值

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

使用未声明的标识符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
    } 
}

协议有点不同。看看“关联类型”

这就是您在示例中使用它的方式

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
    }
}
要详细说明一下,如果您想创建一个使用特定
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)
    }
}

您可以将模板方法与类型擦除一起使用

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"))
protocol-HeavyDelegate:class{
func重型(重型:重型,应返回:P)->R
}  
班重{
typealias参数=P
typealias返回=R
弱var委托:HeavyDelegate?
func注入(p:p)->R{
如果委托!=nil{
返回代理?.heavy(self,shouldReturn:p)
}  
归零
}
func callMe(r:返回){
}
}
类委托:HeavyDelegate{
类型别名H=重型
func重型(重型:重型,应返回:P)->R{
设h=重如!h
h、 叫我(“你好”)
打印(“已调用”)
返回“Hello”作为!R
}  
}
让重
让delegate=delegate()
重载.delegate=委托
重。注入((5,“活着”))

为了实现泛型,并让它像这样声明
让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
    } 
}

如何创建和使用通用协议

协议通用{

associatedtype T
associatedtype U

func operation(_ t:T)->U
}

//使用通用协议

结构测试:通用{

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
    
} 

}

这是一篇非常好的评论,投了赞成票。几个愚蠢的问题:为什么他们决定使用
作为而不是Swift 1.2中的
?第二:您能告诉我为什么我们需要在符合协议的类中再次定义
类型别名
(即
类型别名T=NSDictionary类型别名U=UserModel
)?提前谢谢。我不知道他们为什么从
as
切换到
as。检查devforum。
typealias T=NSDictionary
typealias U=UserModel
不是必需的。我更新了示例以反映这一点。as!表明它可能失败。使开发人员更清楚。它位于答案的底部。请注意,ApiMapperProtocol的唯一用途是用于一般约束。这不像你能写let x:ApiMapperProtocol=UserMapper(),为什么苹果坚持让一切都变得如此违反直觉?@Ben在这种情况下,你如何才能实现let x:ApiMapperProtocol=UserMapper()。@denis\lor如果
x
是本地的,那么你就不需要明确地说出它的类型,所以
let x=UserMapper()@ BeLeGeReRo。我发现如果使用中间泛型类中的一个类,你可以做一些事情,比如让X:APimaPrPrime= UrMaPiPror():这个帖子不包含任何解释。您也已经按原样发布了,请检查我的回答:在这种情况下制定协议有什么意义?它不用于
userMapper
的声明中。
typealias T = UserModel
typealias U = Any

func operation(_ t: UserModel)->Any {
    let dict = ["name":"saurabh"]
    return dict
    
}