在 Swift 中,为什么要有“as”运算符.它有什么好处?他们为什么要投入



我知道as运算符是做什么以及如何使用它们。但我对as运算符的架构方面更好奇。为什么会出现在那里?最大的原因是什么?它有什么帮助?

例:

var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as NSData

。如果是:

var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey")
你有点

困惑是对的,因为在 Swift 1.2 之前,as 关键字被重载了多种含义。 Swift 1.2 使这一点更加清晰,因为现在有 3 个版本的asasas?as! 。 (在以前的版本中,asas!混为一谈,只是as

在您的示例中(我假设它低于 1.2,否则它将无法编译),您正在使用as同时做两件事。

NSUserDefaults.objectForKey的返回类型是一个AnyObject?,一个可选的AnyObject。 也就是说,它可以是任何类型的对象,也可能根本不是对象(因为可能没有为键"myKey"设置值)。

要利用此结果,您需要做两件事 – 解开可选包(即测试它是否包含值),并将AnyObject转换为更有用的类型(在本例中为 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 类型。 if let测试是否存在有效值,以及该值的类型是否正确。

请记住,为"myKey"存储的值可能与您想要的类型不兼容。 假设您想要的不是NSData Int. 你会做if let intData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as? Int. 如果为"myKey"存储的值是字符串"foo",则无法将其转换为Int

,否则会出现错误。

如果不使用上面的as?,而是使用 as ,则强制 Swift 解包值并在不检查的情况下转换类型。 如果一切顺利,那很好。 但是,如果没有值或数据与类型不兼容,您将获得运行时断言,并且程序将崩溃。

这非常危险,以至于在 Swift 1.2 中,这种对as的使用被重命名为 as! ,感叹号部分表示危险的"强制"转换。 如果您尝试在 1.2 中编译示例代码,您将收到一个错误,询问您的意思是as?还是as!

as关键字保留用于始终安全的类型说明。 例如,假设您有一个重载函数,如下所示:

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"

还有一些类型的 Swift <-> Objective-C 桥接转换可以保证始终成功,您也可以将其as用于:

let a = [1,2,3]
// you can always convert a Swift array to an NSArray
let n = a as NSArray
as的好处

是它确认其左侧的对象属于其右侧的类型。例如,它区分以下各项:

myAnimalReallyADog as Dog

myAnimalReallyACat as Dog

如果没有它,您将不得不使用其他可能更冗长的方法来测试对象转换是否合法。

as概念在许多语言中都很常见,并不是 Swift 独有的,所以它是一个成熟的范式,而且很明显很有用。

首先,我们应该知道何时使用它。通常,使用此运算符来执行"向下转换" - 也就是说,运算符尝试将对象引用作为派生类返回 - 并且如果对象实际上是该类型的对象,则成功。这意味着,调用站点必须猜测对象的实际类型。这种倒闭也可能失败。

因此,答案实际上是双重的:

正如OldPeculier已经指出的那样,"这是一个成熟的范式,显然是有用的"。

但是,还有其他更好的设计可以避免可能失败的向下阴影。频繁使用下垂是一种代码气味。你应该努力重新思考你的设计,可能使用协议,或者类扩展等等。

最新更新