質問
私の質問は、子オブジェクトの親にアクセスするためのベスト プラクティスに関するものです。したがって、クラスが別のクラスをインスタンス化し、そのクラス インスタンスがオブジェクトで参照されるようになったとします。その子オブジェクトから親オブジェクトを参照する最善の方法は何でしょうか?現在、よく使用する方法をいくつか知っていますが、A) もっと良い方法があるのか、B) どちらがより良い方法なのかはわかりません。
1 つ目の方法は、getDefinitionByName を使用する方法です。これにより、クラスはインスタンス化されませんが、パブリックに宣言されたクラス内のすべてのものへのアクセスが許可されます。
_class:Class = getDefinitionByName("com.site.Class") as Class;
次に、親から子への階層に基づいてその変数を参照します。
たとえば、子がそれ自身より 2 レベル上のクラスを参照しようとしている場合:
_class(parent.parent).function();
これは問題なく動作しているように見えますが、アクセスしようとしている親のレベルと比較して、子のレベルを知る必要があります。
次のステートメントを取得して、[object ClassName] を Flash の出力にトレースアウトすることもできます。
trace(Class);
私はその行の実装に 100% 賛成しているわけではありません。現在のオブジェクトの外部にあるオブジェクトを参照する方法としてそれを説得していません。
私が使用したことがあるもう 1 つの方法は、単に this への参照を作成しているクラス オブジェクトに渡し、それをコンストラクター引数でキャッチすることです。
var class:Class = new Class(this);
そしてクラスファイル内で
public function Class(objectRef:Object) {
_parentRef = objectRef;
}
ただし、その参照では、子から親への階層を使用してステップアップする必要もあります。
また、そのクラスをインポートし、親であるかどうかに関係なく、直接ファイルパスを使用してそのクラス内のメソッドを参照することもできます。
import com.site.Class;
com.site.Class.method();
もちろん、インポートされたクラスを通じてメソッドまたはプロパティに直接アクセスしているため、親と子の関係は無関係です。
ここで本当に明白な何かが欠けているように感じます。私は基本的に、これらが親を参照する正しい方法であるかどうかを確認したいのです。そうである場合、どれが最も理想的ですか、それとも何か他のものを見落としているのでしょうか?
解決
一般に、クラスを独自のインスタンスとして保持し、他のもの (この場合は親) との密結合を減らすのが良い方法です。parent.doSomething() のようなことを行う場合、 doSometing() メソッドを持たないコンテナでそのクラスを使用することはできません。クラスが必要とするものはすべて渡す方が確実に良いと思います。そうすれば、クラス内でparent.parentなどを行う必要がなくなります。
これにより、将来構造を変更したくなった場合でも、新しい参照を渡すだけで非常に簡単になります。子クラスの実装をまったく変更する必要はありません。
ここでの 3 番目の選択肢も大きく異なり、最初の 2 つのようなインスタンス メソッドではなく、クラス レベルの静的メソッドにアクセスします (そのメソッドにアクセスするときにクラス パス全体を入力する必要はありません)。
他のヒント
一般に、子供が親と通信する必要がある場合は、イベントをブロードキャストして通信させることを検討する必要があります。これにより、子が親から切り離され、他のクラスが子と連携できるようになります。
親クラスへの参照を子に渡すことはお勧めしません。
これは簡単な例です (私がテスト/コンパイルしたので、いくつかのタイプミスがあるかもしれません)。
//Child.as
package
{
import flash.events.EventDispatcher;
import flash.events.Event;
public class Child extends EventDispatcher
{
public function doSomething():void
{
var e:Event = new Event(Event.COMPLETE);
dispatchEvent(e);
}
public function foo():void
{
trace("foo");
}
}
}
//Parent.as
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Parent extends Sprite
{
private var child:Child;
public function Parent():void
{
c = new Child();
c.addEventListener(Event.COMPLETE, onComplete);
c.foo();//traces foo
c.doSomething()
}
public function onComplete(e:Event):void
{
trace("Child broadcast Event.COMPLETE");
}
}
}
ほとんどの場合、カスタム イベントをディスパッチし、それとともにデータを渡します。
基本的に:
親は子への参照を持ち、メソッド呼び出しを介して通信します。子は親への参照を持たず、イベントのディスパッチを通じて(誰とでも)通信します。
それが役立つことを願っています...
マイク・チャンバー
メッシュ@adobe.com
私は常に 2 番目のメソッドを使用して、親オブジェクトへのポインターを子に渡し、そのポインターを子クラスのメンバー変数に格納してきました。私にとって、これは子供が親にコミュニケーションを返す最も簡単な方法のように思えます。
私は親をインターフェイスとして渡すか(そのインターフェイスを実装する親にクラスを含めることができます)、親がフックできるイベント/関数ポインター/デリゲートとして参照を実装することを好みます。
私は、必ずしも子クラスではなく、他のクラスからアクセスする必要があるクラスへの参照を処理するグローバル クラスを設定するのが好きです。
グローバル クラスは、次のような静的なゲッターとセッターで単純に構成されます。
private static const class:Class;
public static function setClass(_class:Class){
class = _class;
}
public static function getClass(void):Class{
return class;
}
これの良い点は、グローバル クラスから返すクラスをインポートする必要がなく、グローバル クラス自体だけをインポートする必要があることです。
参照する必要があるクラスは、それ自体をグローバル リストに追加します。もう 1 つの優れた点は、この一元化された場所からイベントを簡単にディスパッチできることです。
ほとんどの場合、クラスを子クラスまたは他のクラスから参照する必要がある場合、インターフェイスを通じてそれを行います。
これらのオブジェクトが DisplayList に含まれている場合は、さらにいくつかのオプションがあります。ParentClass と ChildClass がある場合、子クラスにリクエストを ParentClass としてキャストすると、親にアクセスできるようです。例えば
ParentClass(parent).parentFunction();
ParentClass が Document クラスの場合に機能することは確かです。ドキュメント クラスは常に表示リストの最初の項目であるため、これは機能します。
ParentClass(stage.getChildAt(0)).parentFunction();
私の場合、それらは両方とも同じパッケージのメンバーだったので、何もインポートする必要さえありませんでした。すべての状況でテストしたわけではありませんが、必要な場合には機能しました。
もちろん、「parent」と「getChild...」は、これらのオブジェクトが DisplayList にある場合にのみ機能しますが、私にとってはそれで十分です。