26

NSObject のサブクラスである「ClassA」を定義して使用するフレームワークを使用しています。いくつかの変数と機能を追加したいので、当然、「ClassA」のサブクラスである「ClassB」を作成しました

今私の問題はこれです。このフレームワーク内のメソッドの多くは、サブクラスにキャストしたい「ClassA」のインスタンスを返します。

たとえば、次の方法を使用します。

- (ClassA *)doSomethingCool:(int)howCool

今私のコードで私はこれを試します:

ClassB * objB;
objB = (ClassB *)doSomethingCool(10); 

NSLog(@"objB className = %@", [objB className]);

これは問題なく動作します。コンパイル エラーや実行時エラーなどはありません。しかし、私にとって本当に奇妙なのは出力です:

>> "objB className = ClassA"

キャスティングは明らかに失敗しました。この時点で何が起こったのかわかりません... objB は「ClassB」と入力されていますが、className は「ClassA」であり、「ClassB」メソッドには応答しません。

これがどのように可能かわかりません...私がここで間違っていることを知っている人はいますか?

ここで求めているものとは正反対の同様の投稿を見つけました

4

5 に答える 5

26

Objective-C でオブジェクト変数をキャストすることは、通常は間違いです (正しい場合もいくつかありますが、この種の場合は決してありません)。オブジェクトをキャストしているのではなく、ポインタをオブジェクトにキャストしていることに注意してください。次に、タイプ のポインターがありますがClassB*、それは依然として ClassA の同じインスタンスを指しています。指摘されていることはまったく変わっていません。

本当に ClassA のインスタンスを ClassB に変換したい場合は、ClassA から ClassB インスタンスを作成できる ClassB コンストラクター メソッドを記述する必要があります。本当にインスタンス変数を追加する必要がある場合は、これが最良の選択かもしれません。

ただし、Jason が言ったように、最初にカテゴリを試してみることをお勧めします。

于 2009-08-06T02:26:43.740 に答える
19

スーパークラスをそのサブクラスにキャストすることはできません。追加された変数/プロパティまたはメソッドは実際には実装されていません。サブクラスで定義したメソッドでメッセージを送信しようとするとすぐに、実行時例外が発生し、アプリケーションが終了します。安全にキャストできるのは、特定の方向から一般的な方向への 1 方向のみです。つまり、ClassA のメソッドとプロパティのみを使用して ClassB を安全に ClassA にキャストできますが、その逆はできません。

次のように考えてください。Car (親クラス) と FourDoorSedan (サブクラス) があります。どの車にもエンジンと 2 つのドアがあります。さて、あなたがどこかから車を手に入れたとしましょう。それについて知っているのはそれだけです。オペレーターに、その車は 4 ドアセダンだと伝えましたが、実際にはそうではないことがわかりました。では、オペレーターが次のような操作を行うと、次のようになります。ドアは2つしかありません!! ここも同じです。

ClassA にちょっとした機能を追加したいだけなら、Objective-C カテゴリをチェックしてください。おそらくそれらはあなたが望むものであり、キャストは必要ありません。ただし、注意事項がないわけではないため、ドキュメントを注意深く読んでください。

于 2009-08-06T01:31:50.003 に答える
2

キャストは、あるタイプのオブジェクトから別のタイプのオブジェクトに変換しません。ファクトリ パターンを使用しない限り、一部のライブラリに強制的にオブジェクトの種類を変更させたり、別の種類のオブジェクトを作成させたりすることはできません。

于 2010-10-30T00:38:09.073 に答える
0

返されたオブジェクトでサブクラス メソッドの 1 つを呼び出すとどうなりますか?

ClassB * objB;
objB = (ClassB *)doSomethingCool(10);
[objB subClassMethod];

Obj-C はかなり自由で、型に負けます。たとえば、事前に型を知る必要さえありません。すべての ClassB 参照を id に変更できます。予想される型を持っていることを知っておく方が安全であることはわかっていますが、コードが正しい場合は問題になりません。

于 2009-08-06T02:20:34.717 に答える