17

SuperclassこのクラスのインスタンスがあるとしましょうsuperclassObject
派生を作成しますClassA

classAObject継承されたすべてのフィールドが のフィールドと等しくなるように、派生クラスのオブジェクトをインスタンス化 (初期化) するにはどうすればよいsuperclassObjectですか?

もちろん、すべてのフィールドを循環して、 のように値を手動でコピーできますclassAObject.property = [superclassObject.property copy]。しかし、このアプローチの問題は、スーパークラスのすべての ivar/プロパティを知らない (またはアクセスできない) 可能性があることです。もっと簡単な(そしてより一般的な)方法はありますか?

本当に基本的なものが欠けているようです...

既に初期化された UIView (フレーム、背景色、自動サイズ変更マスクなど) を取得し、それを同じパラメーターを持つカスタム ビューに置き換えたいため、これを実行しようとしています。

更新 1

私はこの質問を見つけました、そしてそこの答えはそれを言います

通常、どの OO 言語でもサポートされていません

でも

Objective-C では場合によっては可能です

サポートされていない場合は、どうすればよいですか? サポートされている場合、どうすればこれを達成できますか?

更新 2

この一般的な問題の特定のケースに対する解決策を見つけたようです。これをテストして明日報告します。

ただし、これは別のアイデアにつながります: NSCoder を使用して をエンコードしsuperclassObject(もちろん実装する場合)、エンコードされた からのデータを知っているコーダーで<NSCoding>呼び出すとどうなりますか? 免責事項:私はコーディングの概念にあまり詳しくない (またはまったく知らない) ので、最後の文はナンセンスかもしれません。[[ClassA alloc] initWithCoder:coder]superclassObject

4

3 に答える 3

2

私が質問を正しく理解していれば、別のクラスに変更したい確立されたビューがあります。おそらく、機能を変更するためです。

Java のような言語でこの種のことを行う唯一の方法は、クラス間でクラス プロパティを複製し、インスタンスを交換することです。

しかし ... Objective C にはカテゴリがあります。動作を変更するだけの場合、おそらく解決策は、必要な追加またはオーバーライドされた機能を実行する UIView のカテゴリを作成することです。

2番目に考えることは、そもそも正しいクラスを作成していない理由を調べて、この問題全体を回避することです。

于 2011-05-17T23:43:22.907 に答える
0

ObjCランタイムを使用することは間違いなく可能ですが、少し厄介です...これはAppleのドキュメントへのリンクです:Objective-Cランタイムとその使用例:Objective-Cランタイムプログラミング

すべてのプロパティを反復処理し、それらの属性をチェックして設定できるプロパティを見つけ(つまり、読み取り専用プロパティを省略)、スーパークラスでgetterメソッドを取得し、値を読み取り、サブクラスでsetterメソッドを使用して設定します。

UIViewの特定のケースでは、これが機能する可能性があります。機能するまで微調整します。一般的に難しいかもしれません:プロパティとして公開されていないivarはどうですか?それらすべてをコピーしますか?次に、クラスで定義されているプロパティと、クラスが実装するすべてのプロトコルを確認する必要があります。また、定義されたすべてのプロパティとivarを取得するために、スーパークラスのすべてのスーパークラスを反復処理する必要がないかどうかはわかりません。

しかし、それでも可能です。

アップデート

インスタンス変数をコピーする場合は、プロパティに触れることなく設定される可能性があります。最終的には、すべての状態がivarに保存されると思います。したがって、この場合も、プロトコルで定義されたプロパティに触れる必要はありません。

しかし、十分に機能する可能性のある他の解決策は、パブリックインターフェイス(実際にはその一部:機能ではなくデータのように見えるもの)に固執することです:スーパークラスのプロパティを介してデータを読み取り、派生クラスのプロパティを使用して設定します、ここでも、クラスがデータに対して正しいことを行うと仮定します。この場合、プロトコルプロパティも同様に重要です。これは、もパブリックインターフェイスの一部であり、それらの実装によって状態をインスタンス変数に保存できるためです。

繰り返しになりますが、このアプローチをクラスをコピーするための一般的な解決策としては試しませんが、1つの特定のクラスのデータを複製する場合は、十分に機能し、ケースを簡単かつ徹底的にテストできます。

于 2011-05-17T14:49:13.487 に答える
0

サブクラスがメソッドのみをスーパークラスに追加し、ストレージ (ivar など) を追加しない場合は、"isa-swizzling" と呼ばれる半黒魔術の手法* を使用できます。Rob Napierが言及しており、すべてを説明するブログ投稿へのリンクがあります。

各 Objective-C インスタンスには、そのインスタンス変数用のメモリ内のストレージのチャンクがありますが、メソッドの実装はすべて、クラス オブジェクト用のストレージ内の別の場所に保持されます。ランタイムは、インスタンスのisaポインターを使用してクラス オブジェクトを取得します。

したがって、リンクされたブログ投稿で示されているように、フィールドがまったく同じであれば、あるクラスのインスタンスを別のクラスに変換することができます。Rob が警告しているように、ivar を追加することはできず、メソッドを変更するだけです。

キャスト(MyDerivedClass *)instanceOfSuperclassはコンパイル時にのみ効果があります。instanceOfSuperclass型を比較す​​るときにコンパイラを満足させるだけです。メソッドの実行時のルックアップには影響しないため、Superclass.

EDIT:最後の考えとして、すでに危険なテクニックについて話しているので、サブクラスに追加したい ivar を保持するヘルパー クラスを作成することができます。うわー、今私は本当に怒ってしまった !

私はこれを自分でやったことがありません。私はあなたに役立つかもしれないテクニックを報告しているだけです. これについて話し合うときに表示されるすべての警告に注意してください。


*興味深いことに、 KVOに使用されます。

于 2011-05-17T23:45:24.343 に答える