无法执行存储在 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