我知道as
operator做了什么以及如何使用它们。但我对as
运营商的架构方面更加好奇。为什么会这样?原因是什么?它有什么帮助?
示例:
var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as NSData
......如果是这样的话会不会更好:
var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey")
答案 0 :(得分:2)
你有点困惑,因为在Swift 1.2之前,as
关键字已经超载了多个含义。 Swift 1.2使这个很多更清晰,因为现在有as
的3个版本:as
,as?
和as!
。 (在以前的版本中,as
和as!
只是as
}
在您的示例中(我假设它在1.2之前,否则它将无法编译),您正在使用as
同时执行两项操作。
NSUserDefaults.objectForKey
的返回类型为AnyObject?
,可选AnyObject
。也就是说,它可以是任何类型的对象,和它可能根本不是对象(因为可能没有为“myKey”键设置值。)
要使用此结果,您需要做两件事 - 打开可选项(即测试它是否包含值),并将AnyObject
转换为更有用的类型(在本例中为{{ 1}})。
以下是您可以这样做的方法:
NSData
这是使用if let objectData = NSUserDefaults.standardUserDefaults()
.objectForKey("myKey") as? NSData
// note the question mark --^
{
// use the value
}
else {
// handle the value not being present – perhaps set it to a default value
}
暂时测试as?
返回的值是否为objectForKey
类型。 NSData
测试是否存在有效值,以及类型是否正确。
请记住,“myKey”存储的值可能与您想要的类型不兼容。假设您想要if let
而不是NSData
。你做Int
。如果为“myKey”存储的值是字符串“foo”,则无法将其转换为if let intData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as? Int
并且您将收到错误。
如果不使用上面的Int
,而是使用as?
,则强制 Swift解包值并转换类型而不进行检查。如果一切顺利,那很好。但如果没有值或者数据与类型不兼容,您将获得运行时断言,程序将崩溃。
这非常危险,在Swift 1.2中,as
的使用已重命名为as
,感叹部分表示转换的危险“强制”。如果您尝试在1.2中编译示例代码,则会出现错误,询问您是as!
还是as?
。
as!
关键字仍然适用于始终安全的类型说明。例如,假设您有一个像这样的重载函数:
as
还有一些Swift< - > Objective-C桥接转换,保证始终成功,您也可以使用func f(i: Int?) { println("called with Int") }
func f(s: String) { println("called with String") }
// try to call f with nil – Swift will complain because it
// doesn't know if this is a nil int or a nil string
f(nil)
// you can tell it which with as:
f(nil as Int?) // prints "called with Int"
f(nil as String?) // prints "called with String"
:
as
答案 1 :(得分:1)
as
的好处是它确认左侧的对象是右侧的类型。它区分了,例如:
myAnimalReallyADog as Dog
和
myAnimalReallyACat as Dog
如果没有它,你将不得不使用其他的,可能更冗长的方式来测试对象的演员是否合法。
as
概念在许多语言中很常见,并不是Swift独有的,所以它是一个完善的范例,非常有用。
答案 2 :(得分:0)
首先,我们应该知道何时使用它。通常你使用这个操作符来执行" downcast" - 也就是说,操作符尝试将对象引用作为派生类返回 - 如果该对象实际上属于该类,则成功。这意味着,呼叫站点必须对该对象的实际类型进行猜测。这种沮丧也可能失败。
因此,答案实际上是双重的:
正如OldPeculier已经指出的那样,"它是一个完善的范例,显然很有用"。
然而,还有其他更好的设计可以避免可能导致失败的垂头丧气。经常使用垂头丧气是一种代码气味。您应该努力重新考虑您的设计,可能使用协议或类扩展,以便强制使用。