Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.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泛型工厂方法中警告泛型类';X';要求';对象';符合';Y';_Swift_Generics_Factory - Fatal编程技术网

为什么编译器在Swift泛型工厂方法中警告泛型类';X';要求';对象';符合';Y';

为什么编译器在Swift泛型工厂方法中警告泛型类';X';要求';对象';符合';Y';,swift,generics,factory,Swift,Generics,Factory,总而言之,我正在尝试用Swift实现一个数据抽象层。我使用了两个数据库SDK,但我试图将它们的特定API与系统的其余部分隔离开来 我试图实现一个工厂模式,该模式将根据提供的具体类型的协议一致性返回正确的对象。但是编译器给了我一些我无法理解的危险信号 Thing类是一个一级实体,可以在应用程序的逻辑层和UI层中自由移动,某些对象保存在领域存储中(这不重要),并且具有领域对象的子类的特定类型。该类型由一个静态函数返回,该函数必须存在以符合来自DataSourcea的协议 protocol FromD

总而言之,我正在尝试用Swift实现一个数据抽象层。我使用了两个数据库SDK,但我试图将它们的特定API与系统的其余部分隔离开来

我试图实现一个工厂模式,该模式将根据提供的具体类型的协议一致性返回正确的对象。但是编译器给了我一些我无法理解的危险信号

Thing
类是一个一级实体,可以在应用程序的逻辑层和UI层中自由移动,某些对象保存在领域存储中(这不重要),并且具有领域对象的子类的特定类型。该类型由一个静态函数返回,该函数必须存在以符合来自DataSourcea的协议

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()
我现在面临的问题是,当我检查元类型是否符合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 {
            ...
        }
    }
}
类数据目标{
...
func dataSourceBuilder()->DataSource{

如果T.self来自datasourcea{/,那么问题是调用

return DataSourceTypeA(target: self)
在编译时解析,因此检查没有帮助

if T.self is FromDataSourceA { }
运行时。一种可能的解决方案是通过定义受限扩展,将一致性检查作为编译时检查:

extension DataTarget where T: FromDataSourceA {
    func dataSourceBuilder() -> DataSource<T> {
        return DataSourceTypeA(target: self)
    }
}

编译器将根据
target

的静态(编译时)类型信息选择最具体的实现,我有点担心短语“编译器将在解析对该函数的调用时选择最具体的实现”会给人一种印象,带有where子句的多个扩展将作为动态分派和/或函数重载的一种替代。很多人希望这种情况会发生,然后在运行时惊讶于它不会发生(即调用函数的“错误”版本)。谢谢你回答@Martin。我在受限扩展上的约束中添加了
MyObject
,它正在工作。@matt谢谢你的评论-我会保持警惕,并尝试花更多的时间研究这个问题。@Martin可能。:)我可能不必要地担心。毕竟,你说的是“编译器”,这就是重点。只是我看到很多问题,人们试图滥用where子句,比如:还有我的
extension DataTarget where T: FromDataSourceA {
    func dataSourceBuilder() -> DataSource<T> {
        return DataSourceTypeA(target: self)
    }
}
extension DataTarget where T: FromDataSourceB {
    func dataSourceBuilder() -> DataSource<T> {
        // ...
    }
}
extension DataTarget {
    func dataSourceBuilder() -> DataSource<T> {
        // ...
    }
}
let dataSource = target.dataSourceBuilder()