swift - 如何将关联类型约束为协议(protocol)

标签 swift generics protocols

如何将关联类型限制为协议(protocol)。

假设我有以下协议(protocol)和一个实现它的类:

public protocol TestProtocol {
    associatedtype TestType
}

public class TestClass<T : NSCoding>  : TestProtocol {

    public typealias TestType = T

    public func get<T>(_ identifier: String) throws -> T? {
        return "Test" as? T
    }
}

现在一切都很好。 func get 将进行编译,因为编译器知道我的关联类型在这种情况下是一个协议(protocol)。

问题始于这个用例:

public protocol TestProtocol {
    associatedtype TestType

    func get<T>(_ identifier: String) throws -> T? where T : TestType
}

public class TestClass<T : NSCoding>  : TestProtocol {

    public typealias TestType = T

    public func get<T>(_ identifier: String) throws -> T? {
        return "Test" as? T
    }
}

这不会编译,因为编译器不知道在这种情况下 TestType 是否是 ProtocolType。

(它说:“类型'T'仅限于非协议(protocol)类型'TestType'”)

如何强制协议(protocol)中的关联类型“TestType”成为协议(protocol)类型?

编辑:我的第一个示例有点误导,我想要实现的目标的更好定义如下

public protocol TestProtocol {
    associatedtype TestType

    func get<T>(_ identifier: String) throws -> U? where U : TestType
}

public class TestClass<T : NSCoding>  : TestProtocol {

    public typealias TestType = T

    public func get<U>(_ identifier: String) throws -> U? where U : T{
        return "Test" as? U
    }
}

我希望“get”的返回类型为 U 类型并实现协议(protocol) T(我想用它从我的持久性存储中检索数据)。

问题在于该表示法并不强制 T 是协议(protocol)类型(这会导致编译器错误)。我怎样才能强制执行呢?

第二次编辑:

我研究这个问题的时间越长,我就越确信 Swift-Proposal SE-0142 是这个问题的解决方案(也是 swift 4 的一个功能)。

https://github.com/apple/swift-evolution/blob/master/proposals/0142-associated-types-constraints.md

但是如果您有其他想法如何实现所需的行为,请告诉我;)

最佳答案

正如斯巴罗建议的那样:

public protocol TestProtocol {

    associatedtype TestType:Protocol

    func get<TestType>(_ identifier: String) throws -> TestType? 
}

关于swift - 如何将关联类型约束为协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43829986/

相关文章:

ios - 快速导航栏行为

swift - Firebase Cloud Functions 不会从 iOS 应用程序中触发

scala - 高级类型参数中下划线的使用规则

c# - 一种接口(interface)方法的不同类型实现

http - HTTP协议(protocol)使用哪种编码?

ios - 如何检测平移手势并将其仅应用于顶部 subview

ios - Realm:为数据库名称创建全局配置

java - 在Java中,为什么我只能使用泛型来限制集合参数?

ios - Swift 委托(delegate)传递信息

swift - 如何在 Swift 中将 Self 用于方法返回类型?