双数字的类型是Swift中的Int

时间:2016-04-24 11:24:45

标签: swift

// 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"。为什么?
有人可以帮帮我吗? 比你差异很大。

4 个答案:

答案 0 :(得分:10)

Swift数组只能容纳一种类型。当你宣布:

let arr = [1, "a", 2.88]

Swift取得arr[NSObject]。您可以通过选项 - 点击arr来查看其类型。这仅适用,因为您已导入基础(您的import UIKit导入Foundation也是如此)。请尝试删除import UIKit

然后,值12.88已转换为NSNumber"a"转换为NSString,以便将它们存储在[NSObject]中}数组因为Int s,StringDouble s不是NSObjectsNSNumberNSStringNSObject的子类。 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中的asis运算符成功处理任何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还说明了以下内容:

  

...数字对象不一定保留它们的类型   与......