如何在Swift中处理多个通用协议?

时间:2019-02-05 03:55:08

标签: swift generics protocols

我正在尝试使用两个相互关联的通用协议:

protocol PersistableData {}

protocol DataStore: class {
    associatedtype DataType: PersistableData

    func save(data: DataType, with key: String)

    func retreive(from key: String) -> DataType?
}

protocol PersistentDataModel {
    // Swift infers that DataType: PersistableData as DataType == DataStoreType.DataType: PersistableData
    // Setting it explicitly makes the compiler fail
    associatedtype DataType
    associatedtype DataStoreType: DataStore where DataStoreType.DataType == DataType
}

extension String: PersistableData {}

protocol StringDataStore: DataStore {
    associatedtype DataType = String
}


class Test: PersistentDataModel {
    typealias DataType = String
    typealias DataStoreType = StringDataStore
}

但是Xcode未能编译说Type 'Test' does not conform to protocol 'PersistentDataModel'并暗示Possibly intended match 'DataStoreType' (aka 'StringDataStore') does not conform to 'DataStore'StringDataStore被定义为符合DataStore

我已经阅读了一些有关通用协议的很好的资源,包括SO和这个Medium post,但是我找不到问题所在。

1 个答案:

答案 0 :(得分:2)

之所以会这样,是因为您的typealias的{​​{1}}应该是具体的,而不是抽象的。

因此,对于您的情况,associatedtype应该是StringDataStore,而不是class

protocol

但是,您可以继续使用协议并通过在protocol PersistableData {} protocol DataStore: class { associatedtype DataType: PersistableData func save(data: DataType, with key: String) func retreive(from key: String) -> DataType? } protocol PersistentDataModel { // Swift infers that DataType: PersistableData as DataType == DataStoreType.DataType: PersistableData // Setting it explicitly makes the compiler fail associatedtype DataType associatedtype DataStoreType: DataStore where DataStoreType.DataType == DataType } extension String: PersistableData {} class StringDataStore: DataStore { typealias DataType = String func save(data: String, with key: String) { // } func retreive(from key: String) -> String? { return nil } } class Test: PersistentDataModel { typealias DataType = String typealias DataStoreType = StringDataStore } 类中使用其他泛型条件来解决它:

Test

使用此方法,您可以告诉编译器具体类型将被传递到其他地方的class Test<T: StringDataStore>: PersistentDataModel where T.DataType == String { typealias DataStoreType = T typealias DataType = T.DataType }

赞:

Test