在下面的代码中,我想测试x
是否是SpecialController
。如果是,我想将currentValue
作为SpecialValue
获取。如何做到这一点?如果不使用强制转换,则使用其他技术。
最后一行无法编译。错误是:Protocol“SpecialController”只能用作泛型约束,因为它具有Self或关联类型要求。
protocol SpecialController {
associatedtype SpecialValueType : SpecialValue
var currentValue: SpecialValueType? { get }
}
...
var x: AnyObject = ...
if let sc = x as? SpecialController { // does not compile
字符串
4条答案
按热度按时间nue99wik1#
不幸的是,Swift目前还不支持使用协议与关联类型作为实际类型。然而,这需要编译器is technically possible来完成;它很可能会在语言的未来版本中实现。
在您的情况下,一个简单的解决方案是定义一个
SpecialController
派生的“影子协议”,并允许您通过一个协议要求来访问currentValue
,该协议要求可以删除它:字符串
zzoitvuj2#
[编辑以修复:
: SpecialValue
,而不是= SpecialValue
]这是不可能的。
SpecialValueController
在概念上是一个“不完整的类型”,因此编译器无法知道。SpecialValueType
,尽管它 * 受到 *SpecialValue
的约束,但直到它被任何采用类确定时才知道。因此它实际上是一个信息不足的占位符。as?
-ness无法检查。如果您仍在寻求某种程度的多态性,您可以有一个采用
SpecialController
的基类,并为SpecialValueController
提供一个 * 具体 * 类型,并且有多个继承自采用类的子类。33qvvth13#
现在可以在最新版本的Swift中这样做(用5.7测试)
范例:
字符串
输出量:
型
ffx8fchx4#
这是行不通的,因为
SpecialController
不是一个单一的类型。你可以把关联类型看作是一种泛型。一个SpecialController
,它的SpecialValueType
是一个Int
,与一个SpecialController
,它的SpecialValueType
是一个String
,是一个完全不同的类型,就像Optional<Int>
与Optional<String>
是一个完全不同的类型一样。因此,强制转换为
SpecialValueType
没有任何意义,因为这会掩盖相关的类型,并允许您使用(例如)SpecialController
,其SpecialValueType
是Int
,而SpecialController
,其SpecialValueType
是String
。正如编译器所建议的,
SpecialController
可以被用作泛型约束的唯一方式。你可以有一个在T
上泛型的函数,约束是T
必须是SpecialController
。T
的域现在跨越了SpecialController
的所有各种具体类型,比如一个与Int
关联的类型,一个是String
。对于每一个可能的关联类型,都有一个不同的SpecialController
,通过扩展,还有一个不同的T
。为了进一步引出
Optional<T>
的类比。想象一下,如果你正在尝试做的事情是可能的。它会像这样:字符串