在 Swift 中,如何转换为具有关联类型的协议? [英] In Swift, how to cast to protocol with associated type?

查看:31
本文介绍了在 Swift 中,如何转换为具有关联类型的协议?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我想测试 x 是否是 SpecialController.如果是,我想将 currentValue 作为 SpecialValue.你怎么做到这一点?如果不是用演员表,那就是其他一些技巧.

In the following code, I want to test if x is a SpecialController. If it is, I want to get the currentValue as a SpecialValue. How do you do this? If not with a cast, then some other technique.

那里的最后一行不会编译.有错误是:Protocol "SpecialController" 只能用作泛型约束,因为它有 Self 或相关的类型要求.

The last line there won't compile. There error is: Protocol "SpecialController" can only be used as a generic constraint because it has Self or associated type requirements.

protocol SpecialController {
    associatedtype SpecialValueType : SpecialValue
    var currentValue: SpecialValueType? { get }
}
...
var x: AnyObject = ...
if let sc = x as? SpecialController {  // does not compile

推荐答案

不幸的是,Swift 目前不支持使用关联类型作为实际类型的协议.然而,对于编译器来说,技术上是可行的;它很可能会在该语言的未来版本中实现.

Unfortunately, Swift doesn't currently support the use of protocols with associated types as actual types. This however is technically possible for the compiler to do; and it may well be implemented in a future version of the language.

在您的情况下,一个简单的解决方案是定义一个 SpecialController 派生自的影子协议",并允许您通过类型擦除它的协议要求访问 currentValue:

A simple solution in your case is to define a 'shadow protocol' that SpecialController derives from, and allows you to access currentValue through a protocol requirement that type erases it:

// This assumes SpecialValue doesn't have associated types – if it does, you can
// repeat the same logic by adding TypeErasedSpecialValue, and then using that.
protocol SpecialValue {
  // ...
}

protocol TypeErasedSpecialController {
  var typeErasedCurrentValue: SpecialValue? { get }
}

protocol SpecialController : TypeErasedSpecialController {
  associatedtype SpecialValueType : SpecialValue
  var currentValue: SpecialValueType? { get }
}

extension SpecialController {
  var typeErasedCurrentValue: SpecialValue? { return currentValue }
}

extension String : SpecialValue {}

struct S : SpecialController {
  var currentValue: String?
}

var x: Any = S(currentValue: "Hello World!")
if let sc = x as? TypeErasedSpecialController {
  print(sc.typeErasedCurrentValue as Any) // Optional("Hello World!")
}

这篇关于在 Swift 中,如何转换为具有关联类型的协议?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆