2016-04-24 7 views
4
// 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です」と表示されるのはなぜですか?スウィフトの倍数型は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.") 
} 

「この最後はダブルです」。なぜですか?
誰かが私を助けることができますか?
あなたはそれほど変わりません。

答えて

10

スイフトアレイは、1つのタイプしか保持できません。あなたが宣言した場合:

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

スウィフトはタイプ[NSObject]arrを作りました。これを確認するには、オプション-クリックしてarrをタイプしてください。これは、ファウンデーションをインポートしたためにのみ有効です(import UIKitのインポートFoundationも同様です)。 import UIKitを削除してください。

そして、値12.88Int S、String S、及びDouble sはNSObjectsではないので、彼らはその[NSObject]配列に格納することができるようにNSStringNSNumber"a"に変換しました。 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" 

注:

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." 
} 

しかしスウィフトはの配列を作成するつもりはない:あなたはあなたのarr[Any]であることを宣言していた、そして、あなたは予想通り、これは働いているだろうあなたが明示的に尋ねない限り(強く型付けされた言語の忌み嫌われているので)、Anyを入力してください。 [Any]を使用していると思われる場合は、おそらくデザインを考え直すべきです。財団がインポートされココアココアタッチ APIを呼び出すときに、私たちの生活をより簡単にするとき

唯一の理由スウィフトは[NSObject]を作成します。そのようなAPIでNSArrayを渡す必要がある場合は、[NSNumber(integer: 1), NSString(string: "a"), NSNumber(double: 2.88)]の代わりに[1, "a", 2.88]を送信できます。

+0

>次に、値は「NSNumber」に変換されます。しかし、 'last'変数の型をチェックすると' NSNumber'ではなく 'NSObject? 'になります。 – pacification

+0

'last'は、配列が保持する型の任意の変数を返します。配列は '[NSObject]'です。この特定のインスタンスは、NSObjectのサブクラスである2つのNSNumberとNSStringを保持します。 – vacawama

+0

コンパイラはタイプを 'Any'または' [Any] 'に推論することは決してないと思われますので、この配列の型を推論する唯一の方法は' NSNumber'変換を使用して'[AnyObject]'または '[NSObject]'です。 'Foundation'がなければ、コンパイラはエラーを引き起こします。ただし、 '[Any]'を明示的に使用することはできます。 – Sulthan

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. 
} 
0

あなたはタイプ[Any]にして配列を宣言することができます望ましい結果を得る:

あなたはその値型の配列で表現できない数値リテラルで配列リテラルを作成した場合、配列は数字をラップが作成されます。あなたは数字で、特定の魔法の動作を継承 Foundation.frameworkインポートした
let arr: [Any] = [1, "a", 2.88] 
arr.last is Int // false 
0

NSNumberに囲まれています。 Foundationをインポートしない場合(Swift標準ライブラリのみに依存している場合)、let arr = [1, "a", 2.88]のように配列を宣言することは実際にはできません(let arr = [1,2]はまだ動作しますが、[Int]が生成されます) let arr:[Any] = [1, "a", 2.88]を必要とする必要があります。この場合、NSNumberへのボクシングは行われません(NSNumberは使用できません)。元のタイプは何とか保持されます。

するNSNumberはスカラー(数値)の基本的なタイプのすべてのマナーをラップするために使用することができますボックスで、あなたは成功し、それがラップすることができ、数値タイプのいずれかとして任意ののNSNumberを治療するためのスウィフトでasまたはis演算子を使用することができます。

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は、以下を述べて

注:

...数のオブジェクトは、必ずしもそれらが...

で を作成しているタイプを保存しません。

関連する問題