你想要的不是语言的特性,所以你最接近的选择是一个运行时解决方案,它否定了一些属性包装糖。
@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 }
}
}
}