Это происходит потому, что ваш typealias
для 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
где-то еще.
Как это:
class ConcreteStringDataStore: StringDataStore {
func save(data: String, with key: String) {
//
}
func retreive(from key: String) -> String? {
return nil
}
}
let test = Test<ConcreteStringDataStore>()