В качестве обзора я пытаюсь реализовать слой абстракции данных в Swift. Я использую два SDK базы данных, но пытаюсь изолировать их специфические c API от остальной системы.
Я пытаюсь реализовать фабричный шаблон, который будет возвращать правильный Объект основан на соответствии протокола поставляемого конкретного типа. Но компилятор выдает мне красные флажки, которые я не могу обернуть.
Класс Thing
- это объект первого класса, который свободно перемещается по уровням logi c и UI приложения, и некоторые объекты сохраняются в хранилище Realm (что не должно иметь значения) и имеют определенный тип c, который является подклассом объекта Realm. Этот тип возвращается функцией stati c, которая должна быть там, чтобы соответствовать протоколу FromDataSourceA.
protocol FromDataSourceA {
static func A_objectType () -> A_Object.Type
}
class MyObject {
...
}
class Thing: MyObject, FromDataSourceA {
static func A_objectType () -> A_Thing.Type
...
}
// Example usage
let target = DataTarget<Thing>(url: "url")
let dataSource = target.dataSourceBuilder()
Как видите, конкретный тип Thing
соответствует FromDataSourceA
и является передан в инициализатор DataTarget
. DataSourceBuilder
должен иметь возможность проверить, что Thing
соответствует FromDataSourceA
, чтобы иметь возможность вернуть правильный DataSource
.
Класс DataSourceTypeA выглядит как
class DataSourceTypeA<T: MyObject & FromDataSourceA>: DataSource<T> {
let db: DatabaseTypeA // All db-specific APIs contained here
override init (target: DataTarget<T>) {
self.db = try! DatabaseTypeA()
super.init(target: target)
}
override func create<T: MyObject & FromDataSourceA> (object: T) {
db.beginWrite()
db.create(T.A_objectType(), value: object.dict()) // <-- T.A_objectType() is what the conformance to FromDataSourceA is needed for
try! db.commitWrite()
}
override func get<T: MyObject & FromDataSourceA>(id: Int) -> T {
...
}
}
class DataSource<T>: AnyDataSource {
let target: DataTarget<T>
init (target: DataTarget<T>) {
self.target = target
}
func create<T> (object: T) { }
func get<T>(id: Int) -> T { fatalError("get(id:) has not been implemented") }
}
protocol AnyDataSource {
func create<T> (object: T)
func get<T> (id: Int) -> T
}
Проблема, с которой я сейчас сталкиваюсь, заключается в том, что когда я проверяю, что метатип соответствует FromDataSourceA, компилятор выдает мне это предупреждение
class DataTarget<T: MyObject> {
...
func dataSourceBuilder () -> DataSource<T> {
if T.self is FromDataSourceA { // <-- Thing.self conforms to FromDataSourceA
// The Problem:
return DataSourceTypeA(target: self) // Generic class 'DataSourceTypeA' requires that 'MyObject' conform to 'FromDataSourceA'
} else {
...
}
}
}
Почему компилятор не разрешает мне возвращать экземпляр DataSourceTypeA
с аргументом self
если шаблон c T
проходит условное утверждение и доказано, что он соответствует FromDataSourceA
?