Swift protocol generic as function return type

前端 未结 2 903
无人及你
无人及你 2021-01-11 16:18

I want to use generic protocol type as a function return type like this:

protocol P {
  associatedtype T
  func get() -> T?
  func set(v: T)
}

class C<         


        
相关标签:
2条回答
  • 2021-01-11 16:22

    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>())
        }
    }
    
    0 讨论(0)
  • 2021-01-11 16:33

    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>()
    }
    
    0 讨论(0)
提交回复
热议问题