我试图理解as
类型转换。
关于Apple文档的阅读类型转换章节,我有两种向下转换的语法(作为?和!运算符),但我没有找到关于as
的任何内容。
所以我认为我应该永远不会使用这个操作符的扭结,但昨天当我用do-try-catch
语句键入代码时,我遇到了这个:
catch let error as NSError {
print(error)
}
最初,错误类型符合Error protocol
。
现在使用as NSError
转换,它已成为NSError
类的实例。
但我的问题是:运营商做了什么? 这不是一个向下倾斜的确定..它可以用于“转换”对象吗?
修改
我不认为这是重复的。
在我的例子中,错误变量不是一个类,并且不从超类继承,所以我没有向上转换。它甚至不是pattern matching
。
我已经在StackOverflow上阅读了Swift博客页面和这个帖子。
编辑2 来自Swift博客
Swift 1.2分离了保证转换和强制转换的概念 转换成两个不同的运算符。保证转换仍然是 使用as运算符执行,但强制转换现在使用as! 运营商。的!意味着转换可能会失败。 通过这种方式,您可以快速了解哪些转换可能会导致程序 崩溃。
上面的文字对我不起作用,因为如果我尝试使用as!
运算符而不是as
,编译器会抱怨我。
编辑3
即使在Using Swift with Cocoa and Obj-C文档中,它们也使用let-as?
语法来检查和转换为协议。
那么,为什么在我的情况下,我不能使用它?
答案 0 :(得分:1)
将as
用于Apple已完成某些工作以在后台处理转换的类型。这些通常是Apple桥接到Swift的基础类型,并且希望您能够快速地从它们的ObjC等效物来回转换,例如:
String <-> NSString
URL <-> NSURL
Array <-> NSArray
Data <-> NSData
如果您使用as?
或as!
,这些演员表总会成功,Xcode会发出警告。在您的具体情况下,Apple在后台进行了一些干预,使Error
协议和NSError
可以相互转换。
当知道对象可以转换为其他类型时,请使用as!
。如果对象不可投放,则as!
会使您的应用崩溃(例如,当sender
实际上是UITextField
时)
let button = sender as! UIButton // you are sure that the sender is always
// a UIButton or your app will crash
当您不确定对象是否可以转换为其他类型时,请使用as?
。在实践中,这应该是您首选的方法,您应该选择绑定以检查是否成功。如果对象不可投射,as?
会生成nil
:
// Exit the function if the sender is not a UIButton
guard let sender = sender as? UIButton else {
return
}
// Only execute the block if the sender is UIButton
if let button = sender as? UIButton {
// ...
}
答案 1 :(得分:0)
首先,正如dasblinkenlight的评论中所述,您的代码段未使用 type-casting-operator 。检查 do-statement 的语法,您可以找到以下内容:
catch-clause →
catch
pattern选择where-clause选择code-block价值绑定模式→
var
pattern |let
patterntype-casting-pattern → is-pattern | as-pattern
因此, EDIT 2 没有意义, catch-clause 中没有接受as!
的语法。
但是这段代码(使用 type-casting-operator )有效,所以我尝试解释如何使用as
- cast。
enum MyError: Error {
case bad
//...
}
let error: Error = MyError.bad
let nsError = error as NSError
如EI Captain v2.0评论中的链接文章所示,as
- 投射用于保证转换。我收集了一些此类转换的用例。
向上转型
class Animal {}
class Dog: Animal {}
let d = Dog()
d as Animal // upcast succeeds
如文章所示,上传始终成功,因此您可以使用as
。
指定文字类型
let byte = 123 as UInt8
let ch = "a" as UnicodeScalar
在Swift中,文字是无类型的,因此您可以使用as
来指定文字的类型
如果Swift可以推断出文字的类型,你可以省略这样的as
- 施法:
let byte: UInt8 = 123
let ch: UnicodeScalar = "a"
消除重载方法的歧义
class MyClass {
func aMethod(_ arg: String) {
print(arg)
}
func aMethod(_ arg: Int) {
print("\"\(arg)\"")
}
}
let obj = MyClass()
let theFunc = obj.aMethod as (String)->Void
theFunc("abc") //->abc
始终成功的桥接
let str: String = "a String"
let nsStr = str as NSString
let intArr: [Int] = [1,2,3]
let nsArr = intArr as NSArray
示例let nsError = error as NSError
包含在此类别中,您需要仔细阅读this article,以了解为什么这是始终成功的桥接。
对于 EDIT 3 。
您可能需要区分这两种语法:
let a: Any = 1
//Using if-let -- Optional binding, `(a as? Int)` is an expression using type-casting-operator which generates an Optional result
if let intA = (a as? Int) {
print("\(intA) is Int")
}
//Using if-case -- pattern matching, `(let intA as Int)` is a pattern using as-pattern
if case (let intA as Int) = a {
print("\(intA) is Int")
}
如前所述,catch
引导模式,您无法在模式中使用as?
。