Swift protocol generic as function return type
Swift 5.1 supports returning associated types using Opaque type. Using opaque type, your code builds successfully. Ref
protocol P {
associatedtype T
func get() -> T?
func set(v: T)
}
class C<T>: P {
private var v: T?
func get() -> T? {
return v
}
func set(v: T) {
self.v = v
}
}
class Factory {
func createC<T>() -> some P {
return C<T>()
}
The problem is you cannot use the syntax P<T>
. P
is a protocol, meaning it can't be treated as a generic type (Cannot specialize non-generic type 'P'
), even though it may have a given associatedtype
.
In fact, because it has an associatedtype
, you now can't even use the protocol type itself directly – you can only use it as a generic constraint.
One solution to your problem is to simply change your function signature to createC<T>() -> C<T>
, as that's exactly what it returns.
class Factory {
func createC<T>() -> C<T> {
return C<T>()
}
}
I'm not entirely sure what you would gain from having the return type be a protocol here. Presumably your example is just a simplification of your actual code and you want to be able to return an arbitrary instance that conforms to P
. In that case, you could use type erasure:
class AnyP<T> : P {
private let _get : () -> T?
private let _set : (T) -> ()
init<U:P where U.T == T>(_ base:U) {
_get = base.get
_set = base.set
}
func get() -> T? {return _get()}
func set(v: T) {_set(v)}
}
class Factory {
func createC<T>() -> AnyP<T> {
return AnyP(C<T>())
}
}