无法执行存储在 Array[Any] 中的对象的方法
Can't perform methods of objects stored in Array[Any]
我想将不同类型的对象存储在一个数组中。
下面的程序只是一个最小的演示。在 anyArray:[Any] 中存储了 Object1 的一个实例。 print 语句打印出预期的对象类型。在下一行中,存储对象类型的测试 returns 为真。这意味着,在 运行 时间内正确的对象类型是已知的并且一切似乎都很好。
class Object1 {
var name = "Object1"
}
var anyArray:[Any] = [Object1()]
print("\(type(of: anyArray[0]))")
let testResult = anyArray[0] is Object1
print("Test result:\(testResult)")
//print("Name:\((anyArray[0]).name)")
Console output:
Object1
Test result:true
但是,如果我尝试打印出对象的名称 属性,我会收到来自编辑器的错误消息:
Value of type 'Any' has no member 'name'
好吧,在编译时对象的类型是未知的。这就是编译器抱怨的原因。如何告诉编译器可以访问存储对象的属性?
您的对象仍然是 Any
类型。你只是检查它是否可以是 Object1
类型,但你没有转换它。如果你想要对象作为Object1
,你需要cast它。
此外,如果多个 类 可以有名称,您需要使用 Protocol
就像@vadian 在他的评论中提到的那样并将其转换为该协议。
protocol NameProtocol {
var name: String {get set}
}
class Object1: NameProtocol {
var name = "Object1"
}
if let testResult = anyArray[0] as? NameProtocol {
print(testResult.name)
}
编辑: "I want to store objects of different types in an array". 如果您标记的所有对象都正确,则您标记为正确的解决方案将不起作用有不符合协议。
区别来自类型检查的区别:
- 运行时,或
- 编译时间
is
运算符在运行时检查表达式是否可以转换为指定的类型。 type(of:)
在运行时检查确切的类型,而不考虑子类。
anyArray[0].name
无法编译,因为类型 Any
没有 name
属性.
如果您确定 anyArray[0]
是一个 Object1
,您可以使用向下转换运算符 as!
:
print("\((anyArray[0] as! Object1).name)")
要在运行时检查来自 anyArray
的元素是否可以是 Object1
使用可选绑定,使用条件转换运算符 as?
:
如果让:
if let object = anyArray[0] as? Object1 {
print(object.name)
}
或者使用guard
语句,如果你想在其余范围内使用该对象:
guard let object = anyArray[0] as? Object1 else {
fatalError("The first element is not an Object1")
}
print(object.name)
如果您数组中的所有对象都有一个 name
属性,并且您不想反复经历可选绑定的所有环节,那么请使用协议。您的代码将如下所示:
protocol Named {
var name: String {get set}
}
class Object1: Named {
var name = "Object1"
}
var anyArray:[Named] = [Object1()]
print("\(type(of: anyArray[0]))")
let testResult = anyArray[0] is Object1
print("Test result:\(testResult)")
print("Name:\(anyArray[0].name)")
请注意 anyArray
现在是 Named
对象的数组,并且 Object1
符合 Named
协议。
要了解有关协议的更多信息,请查看 here。
我想将不同类型的对象存储在一个数组中。 下面的程序只是一个最小的演示。在 anyArray:[Any] 中存储了 Object1 的一个实例。 print 语句打印出预期的对象类型。在下一行中,存储对象类型的测试 returns 为真。这意味着,在 运行 时间内正确的对象类型是已知的并且一切似乎都很好。
class Object1 {
var name = "Object1"
}
var anyArray:[Any] = [Object1()]
print("\(type(of: anyArray[0]))")
let testResult = anyArray[0] is Object1
print("Test result:\(testResult)")
//print("Name:\((anyArray[0]).name)")
Console output:
Object1
Test result:true
但是,如果我尝试打印出对象的名称 属性,我会收到来自编辑器的错误消息:
Value of type 'Any' has no member 'name'
好吧,在编译时对象的类型是未知的。这就是编译器抱怨的原因。如何告诉编译器可以访问存储对象的属性?
您的对象仍然是 Any
类型。你只是检查它是否可以是 Object1
类型,但你没有转换它。如果你想要对象作为Object1
,你需要cast它。
此外,如果多个 类 可以有名称,您需要使用 Protocol
就像@vadian 在他的评论中提到的那样并将其转换为该协议。
protocol NameProtocol {
var name: String {get set}
}
class Object1: NameProtocol {
var name = "Object1"
}
if let testResult = anyArray[0] as? NameProtocol {
print(testResult.name)
}
编辑: "I want to store objects of different types in an array". 如果您标记的所有对象都正确,则您标记为正确的解决方案将不起作用有不符合协议。
区别来自类型检查的区别:
- 运行时,或
- 编译时间
is
运算符在运行时检查表达式是否可以转换为指定的类型。 type(of:)
在运行时检查确切的类型,而不考虑子类。
anyArray[0].name
无法编译,因为类型 Any
没有 name
属性.
如果您确定 anyArray[0]
是一个 Object1
,您可以使用向下转换运算符 as!
:
print("\((anyArray[0] as! Object1).name)")
要在运行时检查来自 anyArray
的元素是否可以是 Object1
使用可选绑定,使用条件转换运算符 as?
:
如果让:
if let object = anyArray[0] as? Object1 { print(object.name) }
或者使用
guard
语句,如果你想在其余范围内使用该对象:guard let object = anyArray[0] as? Object1 else { fatalError("The first element is not an Object1") } print(object.name)
如果您数组中的所有对象都有一个 name
属性,并且您不想反复经历可选绑定的所有环节,那么请使用协议。您的代码将如下所示:
protocol Named {
var name: String {get set}
}
class Object1: Named {
var name = "Object1"
}
var anyArray:[Named] = [Object1()]
print("\(type(of: anyArray[0]))")
let testResult = anyArray[0] is Object1
print("Test result:\(testResult)")
print("Name:\(anyArray[0].name)")
请注意 anyArray
现在是 Named
对象的数组,并且 Object1
符合 Named
协议。
要了解有关协议的更多信息,请查看 here。