// Swift
import UIKit
let arr = [1, "a", 2.88]
let last = arr.last
if last is Int {
print("The last is Int.") // The last is Int.
} else {
print("The last is not Int.")
}
我无法理解打印的结果 为什么打印"最后是Int"。
// Swift
import UIKit
let arr = [1, "a", -2]
let last = arr.last
if last is Double {
print("The last is Double.") // The last is Double.
} else {
print("The last is not Double.")
}
这个印刷品"最后一个是Double"。为什么?
有人可以帮帮我吗?
比你差异很大。
答案 0 :(得分:10)
Swift数组只能容纳一种类型。当你宣布:
let arr = [1, "a", 2.88]
Swift取得arr
类[NSObject]
。您可以通过选项 - 点击arr
来查看其类型。这仅适用,因为您已导入基础(您的import UIKit
导入Foundation
也是如此)。请尝试删除import UIKit
。
然后,值1
和2.88
已转换为NSNumber
和"a"
转换为NSString
,以便将它们存储在[NSObject]
中}数组因为Int
s,String
和Double
s不是NSObjects
。 NSNumber
和NSString
是NSObject
的子类。 Swift为数组选择了最严格的类型。如果您的数组为[1, true, 2.88]
,则数组类型为[NSNumber]
。
关于NSNumber
的有趣之处在于它是一个包装许多不同类型的对象容器。您可以放入Int
并取出Double
。因此,当您使用is
进行测试时,会产生误导。它响应"真"意思,"如果你想要"我就可以。
import Foundation
let n: NSNumber = 3.14
print(n is Int) // "true"
print(n is Double) // "true"
print(n is Bool) // "true"
print(n as! Int) // "3"
print(n as! Double) // "3.14"
print(n as! Bool) // "true"
注意:如果您宣布arr
为[Any]
,那么这可能会按预期运作:
let arr:[Any] = [1, "a", 2.88]
let last = arr.last
if last is Int {
print("The last is Int.")
} else {
print("The last is not Int.") // "The last is not Int."
}
但除非你明确要求,否则Swift不会为你创建一个Any
类型的数组(因为坦率地说它是强类型语言中的憎恶)。如果您发现自己使用[Any]
,则应该重新考虑您的设计。
导入 Foundation 时,Swift创建[NSObject]
的唯一原因是,在调用 Cocoa 和 Cocoa Touch 时,可以让我们的生活更轻松蜜蜂。如果此类API需要传递NSArray
,您可以发送[1, "a", 2.88]
代替[NSNumber(integer: 1), NSString(string: "a"), NSNumber(double: 2.88)]
。
答案 1 :(得分:0)
问题是你的arr
,如果你宣布
let arr = [1, "a", 2.88] // arr is [NSObject]
所以
let arr = [1, "a", 2.88]
let last = arr.last // last is a NSObject?
if last is Int { // is Int or is Double will get the same result
print("The last is Int.") // because the number of NSNumber is larger than the number of NSString
} else {
print("The last is not Int.")
}
如果你这样声明:
let arr = [1, "a", "b"]
let last = arr.last
if last is Int {
print("The last is Int.")
} else {
print("The last is not Int.") // Will print because the number of NSString is larger than NSNumber.
}
答案 2 :(得分:0)
您可以声明类型为[Any]
的数组,以获得所需的结果:
let arr: [Any] = [1, "a", 2.88]
arr.last is Int // false
答案 3 :(得分:0)
导入Foundation.framework
后,您继承了数字的某种魔术行为:如果您使用无法用该值类型的数组表示的数字文字创建数组文字,则会创建一个包装数组的数组数字装在NSNumber
中。如果你没有导入Foundation(即你只依赖于Swift标准库),那么你实际上不能在let arr = [1, "a", 2.88]
这样的情况下声明数组(而例如let arr = [1,2]
仍然work - 会生成一个[Int]
但需要声明let arr:[Any] = [1, "a", 2.88]
- 在这种情况下,不会发生对NSNumber的装箱(NSNumber甚至不可用),原始类型会以某种方式保留。
NSNumber是一个可用于包装标量(数字)基本类型的所有方式的框,您可以使用Swift中的as
或is
运算符成功处理任何NSNumber它可以包装的数字类型。例如,以下内容成立:
var a = NSNumber(bool: true)
print("\(a is Bool)") // prints "true"
print("\(a is Int)") // prints "true"
print("\(a is Double)") // prints "true"
print("\(a is Float)") // prints "true"
有可能计算出你有时会使用的数字类型,但它不会因某种原因而被NSNumber
暴露出来,但仅在相应的CoreFoundation类型CFNumber
中可用:
extension NSNumber {
var isBoolean:Bool {
return CFNumberGetType(self as CFNumber) == CFNumberType.CharType
}
var isFloatingPoint:Bool {
return CFNumberIsFloatType(self as CFNumber)
}
var isIntegral:Bool {
return CFNumberGetType(self as CFNumber).isIntegral
}
}
extension CFNumberType {
var isIntegral:Bool {
let raw = self.rawValue
return (raw >= CFNumberType.SInt8Type.rawValue && raw <= CFNumberType.SInt64Type.rawValue)
|| raw == CFNumberType.NSIntegerType.rawValue
|| raw == CFNumberType.LongType.rawValue
|| raw == CFNumberType.LongLongType.rawValue
}
}
您可以阅读有关此主题的更多信息over here - 有一些警告。
另请注意,the reference documentation还说明了以下内容:
...数字对象不一定保留它们的类型 与......