简体   繁体   English

Swift 协议通用作为函数返回类型

[英]Swift protocol generic as function return type

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<T>: P {
  private var v: T?
  func get() -> T? {
    return v
  }
  func set(v: T) {
    self.v = v
  }
}

class Factory {
  func createC<T>() -> P<T> {
    return C<T>()
  }
}

But this code compile with errors complained:但是这段代码编译时出现错误:

  1. Cannot specialize non-generic type 'P'不能专门化非泛型类型“P”
  2. Generic parameter 'T' is not used in function signature函数签名中未使用通用参数“T”

Is there any way to achieve similar function with Swift?有没有办法用Swift实现类似的功能?

The problem is you cannot use the syntax P<T> .问题是您不能使用语法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 . P是一个协议,这意味着它不能被视为泛型类型( Cannot specialize non-generic type 'P' ),即使它可能具有给定的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.事实上,因为它有一个associatedtype ,你现在甚至不能直接使用协议类型本身——你只能将它用作通用约束。

One solution to your problem is to simply change your function signature to createC<T>() -> C<T> , as that's exactly what it returns.您的问题的一种解决方案是简单地将您的函数签名更改为createC<T>() -> C<T> ,因为这正是它返回的内容。

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 .据推测,您的示例只是对实际代码的简化,并且您希望能够返回符合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>())
    }
}

Swift 5.1 supports returning associated types using Opaque type. Swift 5.1 支持使用 Opaque 类型返回关联类型。 Using opaque type, your code builds successfully.使用 opaque 类型,您的代码构建成功。 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>()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM