Reputation: 4462
Swift 5.1
I'm writing a class that has a generic parameter T
, and one of its methods accepts a type as an argument, where the type extends from T.Type
. See foo1
below:
public protocol P {
}
public class C: P {
}
public class X<T> {
public func foo1(_ t: T.Type) { // The function in question
}
public func foo2(_ t: P.Type) { // Note that this works as expected, but is not generic
}
}
public func test() {
let x = X<P>()
x.foo1(C.self) // ERROR Cannot convert value of type 'C.Type' to expected argument type 'P.Protocol'
x.foo2(C.self) // Works as expected, but is not generic
}
Now, foo1
works fine when T
is a class. However, when T
is a protocol (e.g. P
), Swift seems to rewrite my function signature from T.Type
to T.Protocol
.
foo1
to accept a type that inherits from P
?Class X
is used in a number of other places - any changes to it must not restrict or remove class parameter T
nor reduce X
's functionality, nor make explicit reference to C
or P
. (It would be acceptable to constrain T
to exclude protocols that do not extend AnyObject
; I don't know how to do that, though. It might also be acceptable to e.g. create a subclass of X
that adds the ability to handle a protocol in T
, but I'm not sure how to do that, either.)
For clarity, this class is used to register classes (t
) that conform to some specified parent (T
), for more complicated project reasons. (Note that classes are being registered, not instances thereof.) The parent is given at the creation of X
, via the type parameter. It works fine for a T
of any class, but I'd also like it to work for a T
of any protocol - or at least for a T
of any protocol P: AnyObject
, under which circumstances foo1
should accept any subclass of P
...the same way it works when T
is a class.
Upvotes: 0
Views: 478
Reputation: 257563
Even though C
is a P
, but C.Type != P.Type
, so the error.
But generics works in a bit different way, like in below examples:
public class X {
public func foo1<T>(_ t: T.Type) { // this way
}
public func foo3<T:P>(_ t: T.Type) { // or this way
}
public func foo2(_ t: P.Type) { // Note that this works as expected, but is not generic
}
}
public func test() {
let x = X()
x.foo1(C.self) // << works
x.foo3(C.self) // << works
x.foo2(C.self) // Works as expected, but is not generic
}
Upvotes: 1