2

我想要做的是有两个泛型类型参数,其中一个是特定类型,另一个是协议,如下所示:

@propertyWrapper
struct Implementation<T, P> where T : AnyObject, T : P { // Compiler error

    var wrappedValue: P { projectedValue }

    var projectedValue: T

    init(_ instance: T) {
        self.projectedValue = instance
    }

}

这样,可以隐藏实际类型,只暴露协议。

现在这不起作用,因为P它是一个非类、非协议类型,所以T不能被限制在它上面。

有没有解决的办法?

4

3 回答 3

0

我认为你可以为 T 创建一个协议来继承,那么你根本不需要 P :

protocol ImplementationProtocol: AnyObject {}

@propertyWrapper
struct Implementation<T: ImplementationProtocol> { 

    var wrappedValue: ImplementationProtocol { projectedValue }

    var projectedValue: T

    init(_ instance: T) {
        self.projectedValue = instance
    }

}

现在你的“T”必须符合“ImplementationProtocol”,“wrappedValue”也必须符合“ImplementationProtocol”,就像你在上面的代码中试图完成的那样。

希望能帮助到你

于 2020-04-22T00:57:06.623 回答
0

你想要的不是语言的特性,所以你最接近的选择是一个运行时解决方案,它否定了一些属性包装糖。

@propertyWrapper
struct Implementation<Object: AnyObject, Protocol> {
  init(_ projectedValue: Object) throws {
    if let error = CastError.Desired(projectedValue, Protocol.self)
    { throw error }

    self.projectedValue = projectedValue
  }

  var projectedValue: Object
  var wrappedValue: Protocol { projectedValue as! Protocol }
}
protocol Protocol { }
class Class: Protocol { init() { } }
struct Struct {
  @Implementation<Class, Protocol> var implementation: Protocol

  init() throws {
    _implementation = try .init( .init() )
  }
}
public enum CastError {
    /// An error that represents that an desired cast is not possible.
  public struct Desired<Instance, DesiredCast>: Error {
    /// `nil` if `instance` is a `DesiredCast`.
    /// - Parameter instance: Anything. 
    public init?(_ instance: Instance, _: DesiredCast.Type) {
      if instance is DesiredCast
      { return nil }
    }
  }

  /// An error that represents that an undesired cast is possible.
  public struct Undesired<Instance, UndesiredCast>: Error {
    /// `nil` if `instance` is not an `UndesiredCast`.
    /// - Parameter instance: Anything. 
    /// - Note: Ineffective if `instance` is a protocol instance
    /// and `UndesiredCast` is `AnyObject`.
    public init?(_ instance: Instance, _: UndesiredCast.Type) {
      guard type(of: instance) is UndesiredCast.Type
      else { return nil }
    }
  }
}
于 2020-04-22T03:50:27.483 回答
-1
@propertyWrapper
struct Implementation<T, P> where T : AnyObject{ 
var wrappedValue: P? = nil

var projectedValue: T {
    didSet {
        if let value =  projectedValue as? P {
                wrappedValue = value
            }
        }
    }

    init(_ instance: T) {
        self.projectedValue = instance
    }

}
于 2020-04-22T01:34:19.747 回答