我在下面列出了一个相当人为的例子来自我正在研究的更大的东西。我遇到了我认为是关于使用Any类型的Swift编译器错误。
struct Labelable <T> {
let t: T
let label: String
}
func allLabels(labelables: [Labelable<Any>]) -> [String] {
return labelables.map { $0.label }
}
let labeledInt = Labelable(t: 22, label: "Steve's Age")
let labeledString = Labelable(t: "Johnson", label: "Stacy's last name")
let labels = allLabels([labeledInt, labeledString])
print(labels)
有问题:
Cannot convert value of type 'Labelable<Int>' to expected element type 'Labelable<protocol<>>'
有没有人对此问题和任何变通方法有任何见解?或许,有一种更好的方法来完成我想要做的事情?
由于
编辑:
这就是我最终要做的事情。啊。
protocol LabelableProtocol {
var label: String { get }
}
struct Labelable <T>: LabelableProtocol {
let t: T
let label: String
}
func allLabels(labelables: [LabelableProtocol]) -> [String] {
return labelables.map { $0.label }
}
let labeledInt = Labelable(t: 22, label: "Steve's Age")
let labeledString = Labelable(t: "Johnson", label: "Stacy's last name")
let labels = allLabels([labeledInt, labeledString])
print(labels)
答案 0 :(得分:1)
这里的问题是Any
不是类型,而是协议。您可以通过尝试通过其他协议扩展它来看到这一点(不允许其他协议的协议扩展):
protocol MyDummyProtocol {}
extension Int : MyDummyProtocol {} // OK
extension Any : MyDummyProtocol {}
//Error: Non-nominal type Any (aka protocol<>) cannot be extended.
因此,在调用allLabels
时,您无法将Int
或String
类型转换为Any
协议。
但是,您可以在结构中专门使用Any
作为通用T
:
let labelAny = Labelable<Any>(t: 22, label: "Steve's Age")
let labelAnyAgain = Labelable<Any>(t: "Johnson", label: "Stacy's last name")
let labels = allLabels([labelAny, labelAnyAgain]) // OK
但是,这里更有趣的是研究结构中的通用属性t
。现在应该是Any
,对吧?关于Any
的好处是我们可以将它转变为基本的快速类型。例如,考虑:
struct Labelable <T> {
let t: T
let label: String
}
func allGenerics(labelables: [Labelable<Any>]) -> [Any] {
return labelables.map { $0.t }
}
let labelAny = Labelable<Any>(t: 22, label: "Steve's Age")
let labelAnyAgain = Labelable<Any>(t: "Johnson", label: "Stacy's last name")
let labelsGeneric = allGenerics([labelAny, labelAnyAgain])
for label in labelsGeneric {
switch label {
case is Int: print("is int: " + "\(label)")
case is String: print("is string: " + "\(label)")
default: print("Default...")
}
}
// Prints:
// is int: 22
// is string: Johnson
在这里,我们使用Any
作为通用(即使它特别是Any
),然后简单地让向下投射is
成为我们的通用行为。
有关详细信息,请参阅Language Guide - Type Casting - Type Casting for Any and AnyObject。
任何可以表示任何类型的实例,包括函数类型。
...
仅当您明确需要行为时才使用Any和AnyObject 他们提供的能力。具体而言总是更好 您期望在代码中使用的类型。