问题
I am implementing a generic collection and I would like to make its usage with types/protocol hierarchy more convenient. I stumbled on the following question.
How one does implement a collection
class SpecialSet<ObjectType> {
Such that given two types B : A
one can perform implicite conversion of SpecialSet<B>
into SpecialSet<A>
?
I am suprised but I wasn't able to find any documentation explaining this simple concept that indeed exist for the Array collection. This swift code is indeed valid:
let b = [B(), B(), B()]
let a: [A] = b
I probably do not used the right vocabulary in my searches.
I tried to define a constructor as follow but it seams not possible to enforce inheritance between two generic.
init<T>(_ specialSet: SpecialSet<T>) where T: ObjectType {
回答1:
It has always been impossible.
Swift generics are normally invariant, but the Swift standard library collection types — even though those types appear to be regular generic types — use some sort of magic inaccessible to mere mortals that lets them be covariant.
Potential workaround. 🤷♂️
protocol Subclass: AnyObject {
associatedtype Superclass
}
extension B: Subclass {
typealias Superclass = A
}
class SpecialSet<Object>: ExpressibleByArrayLiteral {
required init(arrayLiteral _: Object...) { }
init<T: Subclass>(_: SpecialSet<T>) where T.Superclass == Object { }
}
let specialSetB: SpecialSet = [B(), B()]
let specialSetA = SpecialSet<A>(specialSetB)
来源:https://stackoverflow.com/questions/61597358/how-to-allow-a-generic-collection-to-perform-under-the-hood-conversion-in-swift