【问题标题】:Swift array of Generics with protocols [duplicate]带有协议的 Swift 泛型数组 [重复]
【发布时间】:2017-03-28 07:16:49
【问题描述】:

我只是好奇是否可以执行以下操作

protocol Data { }

class A: Data { }

class B: Data { }

class Generic<T> { }

class doStuff {

    func prepareToDoStuff() {
        self.doTheStuffWithGenerics([Generic<A>(), Generic<B>])
    }

    func doTheStuffWithGenerics<T: Generic<Data>>(_ generics: [T]) {

    }
}

目前我的编译器告诉我不要说

"无法将 'Generic[A]' 类型的值转换为预期的元素类型 '通用[数据]'"

有什么想法吗?解决方案?

【问题讨论】:

标签: arrays swift generics protocols


【解决方案1】:

其他人已经解释了为什么不起作用。所以我只关注解决方法。 Apple 自己解决此问题的方式(例如查看Collection 协议)是使用协议。将您的逻辑移至 Generic 类或在您的协议上使用扩展类是很常见的。

例如:

protocol Data { }
protocol GenericDataType {
    func doStuff()
}

class A: Data { }
class B: Data { }


class Generic<T: Data>: GenericDataType {
    func doStuff() {
        print("Processing element")
    }
}

class doStuff {

    func prepareToDoStuff() {
        let array: [GenericDataType] = [Generic<A>(), Generic<B>()]
        self.doTheStuffWithGenerics(array)
    }

    func doTheStuffWithGenerics(_ generics: [GenericDataType]) {
        for element in generics {
            element.doStuff()
        }
    }
}

【讨论】:

    【解决方案2】:

    您正在寻找的功能是通常称为泛型类型的variance。类型的方差描述了该类型的不同实例之间的子类型关系如何随其类型参数而变化。

    Java 通过其类型通配符结构对此提供支持。使用这个结构,你的例子可以写成这样:

    // "? extends Data" means: Some specific but unknown type which extends Data
    func doTheStuffWithGenerics(_ generics: [Generic<? extends Data>]) {
    
    }
    
    func prepareToDoStuff() {
        // This would be okay because both A and B are *some type that extend Data*
        self.doTheStuffWithGenerics([Generic<A>(), Generic<B>])
    }
    

    从其他答案来看,Swift 不支持任何类型的变体泛型类型(目前)。

    通配符说明

    ? extends Data 类型是 Generic 的参数类型,它有一些不寻常的属性:

    • 当您从具有此类型的字段中读取时,您将获得 Data 类型的对象。
    • 不可能写入这种类型的字段!因为实际的字段有一些未知的类型,编译器永远不会知道你给它写了正确的对象类型。

    【讨论】:

      【解决方案3】:

      由于ABData 是不同的类型(不是对象),因此您将无法执行此类操作。将Generic&lt;A&gt; 转换为Generic&lt;Data&gt; 是没有意义的——因为它们都有不同的类型参数。

      【讨论】:

        【解决方案4】:

        Swift 是静态类型的,这意味着编译器需要在编译时准确地知道每个变量的具体类型。

        从这个角度来看,Generic&lt;A&gt;Generic&lt;B&gt;Generic&lt;Data&gt; 是三种不同的类型。这与ABData 不同。

        由于AB 符合Data,因此您可以将[A(), B()] 转换为类型[Data]let a = [A(), B()] as [Data])。

        Generic&lt;A&gt;Generic&lt;B&gt;Generic&lt;Data&gt; 之间没有这种“符合”关系。因此[Generic&lt;A&gt;(), Generic&lt;B&gt;()]不能转换为[Generic&lt;Data&gt;]类型,只能转换为[Any],显然Any不能转换为预期的元素类型Generic&lt;Data&gt;

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-09-10
          • 2023-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-12
          相关资源
          最近更新 更多