3

重複の可能性:
NSStrings を指定すると、高速列挙が NSNumbers をスキップしないのはなぜですか?

最近、高速列挙を使用しているときに予期しない動作に気付きました。後から考えると、おそらく高速な列挙が意図した以上のことを行うことを期待していたので、実際にどのように機能するかについての説明を探しています。

2 つの子クラス3SidedShape4SidedShapeを持つ親クラスShapeがあるとします。3 面と 4 面の両方のクラスのオブジェクトを含むmyShapesという配列があります。

配列myShapesを検索したいが、私がやっていたことは 3 つの側面の形状だけに関心がある場合:

 for (3SidedShape *shape in myShapes)

私の考えでは、クラス3SidedShapeのオブジェクトのみを反復処理すると思いましたが、そうではありませんか? 好むと好まざるとにかかわらず、すべてのオブジェクトを3SidedShapeとしてキャストしていると思います。私は完全に異なるクラスとして後でオブジェクトを返す夜です。確かに、両方のクラスにないメソッドを呼び出しているわけではありませんが、クラスの兄弟が問題なく簡単に再キャストされるとは思っていませんでした。私はここでラッキーだったのですか、それとも関係に関係なく好きなクラスとして列挙できますか? 列挙中に実際に何が起こるか説明できる人はいますか?

4

1 に答える 1

3

for...inループ (別名高速列挙) で指定された型は、コレクション内のすべての要素を指定された型にキャストします。それらが「簡単に再キャストされる」理由は、キャストによってあるタイプのオブジェクトが別のタイプに変換されないためです (それはどのように機能しますか?)。これは、オブジェクトを別の型であるかのように扱うようにコンパイラに指示するヒントです。「心配しないでください。このオブジェクトは(insert type)のオブジェクトなので、そのように型をチェックしてください」と言うかのように。オブジェクトが処理できないが、キャストされた型が処理できるメッセージをオブジェクトに送信すると、アプリがクラッシュします。あなたがすべきことはこれです:

for (id shape in myShapes){
    if ([shape isKindOfClass: [3SidedShape class]]){
        //insert code here
    }
}

そのコードは型を想定しておらず、イントロスペクションを使用して、型が3SidedShapeまたは 3SidedShape のサブクラスであるオブジェクトに対してのみコードを実行します。正確なチェック (サブクラスを除く) には、isMemberOfClass:を使用します。ただし、クラス クラスタ (NSNumber) 内のクラスのメンバーシップをテストするためにisMemberOfClass:を使用することには注意してください。これは、より複雑な内部実装のためです。

于 2012-09-11T01:55:08.947 に答える