Swift 类型推断和类型检查问题
Swift type inference and type checking issue
我不是在寻找答案,比如如何正确地做到这一点,而是为什么会发生这种情况。
代码如下:
func isInt(param: AnyObject?) {
if let value = param as? Int {
print(value)
} else {
print("Not Int")
}
if let value = param {
if value is Int {
print(value)
} else {
print("Not Int")
}
}
}
let a:AnyObject? = 1.2
let b:Float? = 1.2
let c:Double? = 1.2
isInt(a)
isInt(b)
isInt(c)
我理解在第一个 if
循环中,param
被转换为 Int
然后打印出 1
。
但是为什么在第二个if
循环中,if value is Int
为真然后打印出1.2
?
好吧,如果您执行以下操作,似乎就可以了:
func isInt(param: AnyObject?) {
if let value = param {
if value is Double {
print("I'm a double")
}
if value is Int{
print("I'm an int")
}else {
print("Not Int")
}
}
}
它将为所有三个打印 "I'm a double" 并且也为所有三个打印 "I'm an int"。似乎当它转到 if 语句时,它将值桥接到 NSNumber,这对于任何 NSNumber 类型都是如此。
但是,假设您执行以下操作:
if let value = param {
if value is String {
print("I'm a String")
}
if value is Int{
print("I'm an int")
}else {
print("Not Int")
}
}
}
由于 String 不是 NSNumber 类型,它将跳过并转到如果值是 Int,它是 NSNumber 类型和 return 值。
在您的 b
案例中,let value = param
将 value
桥接到 NSNumber
类型。对于 NSNumber
,value is Int
将始终为真。
对于未桥接的值:
a is Int // always true, AnyObject bridges to NSNumber here
b is Int // false, cast from Float to Int always fails
c is Int // false, cast from Double to Int always fails
此答案假定 Foundation 已导入。没有 Foundation,您的作业将失败。
Instances of the Swift numeric structure types, such as Int, UInt, Float, Double, and Bool, cannot be represented by the AnyObject type, because AnyObject only represents instances of a class type. However, when bridging to Foundation is enabled, Swift numeric values can be assigned to constants and variables of AnyObject type as bridged instances of the NSNumber class.
我们可以在 Playground 中看到这一点:
let value = 1.2
value.dynamicType //Double.Type
value is Int //false
let castValue = value as AnyObject
castValue.dynamicType //__NSCFNumber.Type (a private framework class, part of the NSNumber class cluster)
//NSNumber is bridged to Int, UInt, Float, Double, and Bool so `is` tests for those types will return `true`
castValue is Int //true
castValue is Float //true
//NSNumber is not bridged to String so an `is` test will return `false`
castValue is String //false
我不是在寻找答案,比如如何正确地做到这一点,而是为什么会发生这种情况。
代码如下:
func isInt(param: AnyObject?) {
if let value = param as? Int {
print(value)
} else {
print("Not Int")
}
if let value = param {
if value is Int {
print(value)
} else {
print("Not Int")
}
}
}
let a:AnyObject? = 1.2
let b:Float? = 1.2
let c:Double? = 1.2
isInt(a)
isInt(b)
isInt(c)
我理解在第一个 if
循环中,param
被转换为 Int
然后打印出 1
。
但是为什么在第二个if
循环中,if value is Int
为真然后打印出1.2
?
好吧,如果您执行以下操作,似乎就可以了:
func isInt(param: AnyObject?) {
if let value = param {
if value is Double {
print("I'm a double")
}
if value is Int{
print("I'm an int")
}else {
print("Not Int")
}
}
}
它将为所有三个打印 "I'm a double" 并且也为所有三个打印 "I'm an int"。似乎当它转到 if 语句时,它将值桥接到 NSNumber,这对于任何 NSNumber 类型都是如此。
但是,假设您执行以下操作:
if let value = param {
if value is String {
print("I'm a String")
}
if value is Int{
print("I'm an int")
}else {
print("Not Int")
}
}
}
由于 String 不是 NSNumber 类型,它将跳过并转到如果值是 Int,它是 NSNumber 类型和 return 值。
在您的 b
案例中,let value = param
将 value
桥接到 NSNumber
类型。对于 NSNumber
,value is Int
将始终为真。
对于未桥接的值:
a is Int // always true, AnyObject bridges to NSNumber here
b is Int // false, cast from Float to Int always fails
c is Int // false, cast from Double to Int always fails
此答案假定 Foundation 已导入。没有 Foundation,您的作业将失败。
Instances of the Swift numeric structure types, such as Int, UInt, Float, Double, and Bool, cannot be represented by the AnyObject type, because AnyObject only represents instances of a class type. However, when bridging to Foundation is enabled, Swift numeric values can be assigned to constants and variables of AnyObject type as bridged instances of the NSNumber class.
我们可以在 Playground 中看到这一点:
let value = 1.2
value.dynamicType //Double.Type
value is Int //false
let castValue = value as AnyObject
castValue.dynamicType //__NSCFNumber.Type (a private framework class, part of the NSNumber class cluster)
//NSNumber is bridged to Int, UInt, Float, Double, and Bool so `is` tests for those types will return `true`
castValue is Int //true
castValue is Float //true
//NSNumber is not bridged to String so an `is` test will return `false`
castValue is String //false