【发布时间】:2016-01-28 02:17:21
【问题描述】:
今天在玩 Swift 时,我遇到了一件奇怪的事情。这是我开发的单元测试,它显示了使用 Swift 的 AnyObject 时的一些意外行为。
class SwiftLanguageTests: XCTestCase {
class TestClass {
var name:String?
var xyz:String?
}
func testAccessingPropertiesOfAnyObjectInstancesReturnsNils() {
let instance = TestClass()
instance.xyz = "xyz"
instance.name = "name"
let typeAnyObject = instance as AnyObject
// Correct: Won't compile because 'xyz' is an unknown property in any class.
XCTAssertEqual("xyz", typeAnyObject.xyz)
// Unexpected: Will compile because 'name' is a property of NSException
// Strange: But returns a nil when accessed.
XCTAssertEqual("name", typeAnyObject.name)
}
}
此代码是其他一些代码的简化,其中有一个 Swift 函数只能返回 AnyObject。
正如预期的那样,在创建TestClass 的实例后,将其强制转换为AnyObject 并设置另一个变量,访问属性xyz 将无法编译,因为AnyObject 没有这样的属性。
但令人惊讶的是,编译器接受了一个名为 name 的属性,因为在 NSException 上有一个名为该名称的属性。看起来 Swift 很乐意接受任何属性名称,只要它存在于运行时的某个位置。
下一个意想不到的行为和开始这一切的原因是尝试访问name 属性返回一个nil。观察调试器中的各种变量,我可以看到 typeAnyObject 指向原始的 TestClass 实例,它的 name 属性的值为“名称”。
Swift 在访问typeAnyObject.name 时不会抛出错误,所以我希望它能够找到并返回“名称”。但相反,我得到了 nil。
如果有人能对这里发生的事情有所了解,我会很感兴趣?
我主要担心的是,我希望 Swift 在访问 AnyObject 上不存在的属性时抛出错误,或者找到并返回正确的值。目前两者都没有发生。
【问题讨论】: