3

Flash、actionscript 3 で OOP 関連の問題があります。これは個人的なプロジェクトであり、この問題のデザイン パターンまたは回避策を探しています。私の目標は、新しいことを学ぶことです。

Chainというクラスを作成しました。遅延関数呼び出しを簡単にするために、この util-class を作成しました。ミリ秒単位の遅延で関数を追加することで、一連の関数を作成できます。このチェーンは、逆の順序であっても、複数回実行できます。このクラスには、自分自身を返す関数があります。これにより、次のような jQuery スタイルの構文を使用できるようになります。

var chain:Chain = new Chain(); 
chain.wait(100).add(myFunction1,300).wait(300).add(myFunction2,100);
// etc..

この例では、問題を示すためだけに多くの関数を残しました。Chain クラスは、ほとんどの場合、関数を追加してチェーンを開始/停止するためのものです。

public class Chain 
{  
 function wait(delay:int = 0):Chain
 {
   // do stuff
   return this;
 }

 public function add(func:Function, delay:Number = 0):Chain
 {
      list.push( new ChainItem(func, delay) );
      return this;
 }
}

今、ChainTween という別のクラスがあります。いくつかのコア機能を備えたチェーンを維持し、ChainTween にいくつかのアニメーションのトリックを実行させるために、物事を分割しようとしています。私は、Chain クラスに基づいて小さなトゥイーン エンジンを作成するというアイデアを思いつきました。現在、Chain を拡張しています。Chain クラスからの保護された変数を多数使用し、Chain のいくつかのコア関数もオーバーライドして、Chain のプロセス内にトゥイーン関数を追加します。

public class ChainTween extends Chain
{  
 function animate(properties:Object = null, duration:Number = 0, easing:Function = null):ChainTween
 {
   // do stuff
   return this;
 }
}

これが問題です。連鎖構文を維持したいのですが、wait() は Chain インスタンスを返し、Chain にはアニメーション関数がありません。

var chain:ChainTween = new ChainTween();
chain.wait(100).animate({x:200}, 100).wait(250);

ChainTween クラスの wait() および add() 関数をオーバーライドしようとしましたが、互換性のないオーバーライドが発生します。

chain.wait(100) を ChainTween としてキャストすることもできますが、これは非常に見苦しく、多数のチェーンを使用する場合には役に立ちません。ここで、ChainTween 関数を Chain に追加したくありません (ダミー関数もありません)。また、すべての関数の補完を保持したいので、Object を返すこともできません。インターフェイスを使用しようとしましたが、インターフェイスの関数はそれを実装するクラスに実装する必要があるため、これも同じ問題を引き起こします。

ここで、ChainTween 内に Chain のインスタンスを作成することを考えましたが、これでは関数をオーバーライドできないため、多くのプロパティを保護する代わりに公開する必要がありますが、これも好ましくありません。

これは可能ですか?これに対する優れた解決策はありますか?

4

6 に答える 6

2

この問題は非常に一般的です。使用している設計パターンはFluent Interfaceと呼ばれ、「Fluent Interface Inheritance」を Google で検索すると、多くの質問とほとんど答えが見つかりません。

C#、Java、およびC++ でこれを解決する一般的な方法は、テンプレートを使用することです。ただし、AS3 で同じものを実装する方法はわかりません。このトピックが役立つ可能性があります。

于 2010-12-17T15:02:30.697 に答える
1

Chain クラスの構造に従えば、add メソッドを使用して animate メソッドを呼び出すことが可能 (かつ論理的) であるはずです... Chain クラスについて詳しく知らないため、より正確にすることは困難ですが、理論的には可能だと思われます... add メソッドに新しい引数を追加する必要があります。

var chain:ChainTween = new ChainTween();
var params:Object = {x:200};
chain.wait(100).add(animate, 300 , params).wait(300);

alxxにはポイントがあります.Javascriptとは異なり、AS3は厳密に型指定された言語であり、これが制限の原因です。回転、フェードアウトのように具体的なメソッドを実装する必要がある場合、利用できるソリューションはそれほど多くないかもしれません。これらのメソッドは、ChainTween、Chain、または Object のいずれかを返し、Object と * ... の両方を却下しています。

どういうわけか、私はまだ、回転、フェードアウト、またはアニメーション メソッドを add() (またはその目的のために作成する他のメソッド) で追加することは、Chain の設計とより一致していると思います。

于 2010-12-17T13:33:12.193 に答える
1

コード補完によって関数をリストしたい場合は、そこになければなりません。これにより、実行時の検出方法が除外されます。次のようなものを Chain に追加します。

public function animate(args:Object, time:int):Chain {
    throw new Error("Animate is supported only on ChainTween");
}

ChainTween でオーバーライドされます。そんなに大げさだと思わないでください。

于 2010-12-17T10:28:00.030 に答える
0

私はすでに提案されているインターフェースのアイデアに行きます。Wait は、ChainTween を構成するメソッドのみを含む「IChainTween」のようなものと、元のチェーンを返す「then」のような関数を返します。

package
{
    public interface IChainTween
    {
        function doSomething():IChainTween;
        ...
        function then():IChain;
    }
}

package
{
    public class ChainTween implements IChainTween
    {
        private originalChain:IChain;
        public function ChainTween(IChain chain)
        {
            originalChain = chain;
        }
        ...
        public function doSomething():IChainTween
        {
            return this;
        }
        public function then():IChain
        {
            return originalChain;
        }
    }
}
于 2010-12-17T16:48:21.857 に答える
0

Chain の代わりに * を返すこともできますが、これによりコード ヒントが削除されます。

于 2010-12-17T10:56:43.707 に答える
0

もし私があなただったら、コア機能 ( など) だけを記述したインターフェースを作成しますIChainaddwait

于 2010-12-17T11:29:54.347 に答える