In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

パラメータコンテナのテスト

汎用パラメータコンテナクラスのテストコード 2010/08/22
* 
* Tweener.addTween() などにおいて {name: value, ... } の形式で
* パラメータを渡しますが、自身のコードでこのようなパラメータを汎用的に
* 制御したい場合どうすればよいか?ということで、基底パラメータコンテナ
* となるクラス BaseParamContainer を作ってみました。
* 
* 基底クラスを継承した(自分の使いたい)パラメータコンテナを定義し、
* コンテナを生成する際に {name: value, ... } の形式でパラメータを
* 流し込むイメージです。強制的に型が合うものを設定するだけのシンプルな
* 構造であるため定義側も呼出側も扱いは難しくないと考えます。
* 
* 現在作っている表示オブジェクトの Link クラス用のパラメータとして
* この仕掛けを使おうと思ってます。極小規模の開発では、この手の枠組みは
* 冗長だと考えますが、部品群の開発と表面側の実装が分かれるような
* 開発シーンで、多くのパラメータを受け渡しする場合、便利だと思いますが
* どうでしょう?
Get Adobe Flash player
by zier 22 Aug 2010
/**
 * Copyright zier ( http://wonderfl.net/user/zier )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/sLT1
 */

/*
 * 汎用パラメータコンテナクラスのテストコード 2010/08/22
 * 
 * Tweener.addTween() などにおいて {name: value, ... } の形式で
 * パラメータを渡しますが、自身のコードでこのようなパラメータを汎用的に
 * 制御したい場合どうすればよいか?ということで、基底パラメータコンテナ
 * となるクラス BaseParamContainer を作ってみました。
 * 
 * 基底クラスを継承した(自分の使いたい)パラメータコンテナを定義し、
 * コンテナを生成する際に {name: value, ... } の形式でパラメータを
 * 流し込むイメージです。強制的に型が合うものを設定するだけのシンプルな
 * 構造であるため定義側も呼出側も扱いは難しくないと考えます。
 * 
 * 現在作っている表示オブジェクトの Link クラス用のパラメータとして
 * この仕掛けを使おうと思ってます。極小規模の開発では、この手の枠組みは
 * 冗長だと考えますが、部品群の開発と表面側の実装が分かれるような
 * 開発シーンで、多くのパラメータを受け渡しする場合、便利だと思いますが
 * どうでしょう?
 */
package {
    import flash.display.DisplayObjectContainer;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.utils.describeType;
    import com.bit101.components.PushButton;
    
    [SWF(width=465, height=465)]
    public class FlashTest extends Sprite {
        
        private var memo: TextField
        
        public function FlashTest() {

            function createTextField(p: DisplayObjectContainer, x: Number, y: Number, w: Number, h:Number): TextField {
                var t: TextField = new TextField()
                t.x = x; t.y = y; t.width = w; t.height = h; p.addChild(t)
                return t
            }
            
            function createButton(p: DisplayObjectContainer, x: Number, y: Number, c: String, f: Function): PushButton {
                return new PushButton(p, x, y, c, f)
            }
            
            var title: TextField = createTextField(this, 10, 10, 200, 20)
            title.scaleX = title.scaleY = 2
            title.text = "BaseParamContainer test code"
            
            createButton(this,  10, 50, "case 1", case1).width = 60
            createButton(this,  80, 50, "case 2", case2).width = 60
            createButton(this, 150, 50, "case 3", case3).width = 60
            createButton(this, 220, 50, "case 4", case4).width = 60
            createButton(this, 290, 50, "case 5", case5).width = 60
            createButton(this, 360, 50, "case 6", case6).width = 60
            
            memo = createTextField(this, 10, 80, 430, 360)
            memo.wordWrap = true
            memo.border = true
        }
        
        private function init(msg: String): void { memo.text = msg + "\n-----" }
        
        private function list(param: Object): void {
            for each(var variable:XML in describeType(param)..variable) {
                var n: String = variable.@name
                memo.appendText("\n" + n + ":" + param[n])
            }
        }
        
        private function case1(e: MouseEvent = null): void {
            init("test case 1:\nそのままパラメータコンテナを生成した場合\nデフォルト値を使ったパラメータコンテナを生成する")
            list(new SampleParam())
        }
        
        private function case2(e: MouseEvent = null): void {
            init("test case 2:\nパラメータを渡してコンテナを生成した場合\n渡されたパラメータに従って、内容を更新できる")
            list(new SampleParam( { tail: this, lineWidth: 5, lineColor: 0xff0000, fillColor: 0xc00000, fill: true } ))
        }
        
        private function case3(e: MouseEvent = null): void {
            init("test case 3:\nstatic な factory method を使う事も問題なし\nこれで呼出側に対して、複数のデフォルトパラメータを提供できる")
            list(SampleParam.create())
        }
        
        private function case4(e: MouseEvent = null): void {
            init("test case 4:\nプリミティブ型に対して型が違うパラメータを渡した場合は、\n設定は無視され、デフォルト値が優先される")
            list(new SampleParam( { fillColor: "A" } ))
        }
        
        private function case5(e: MouseEvent = null): void {
            init("test case 5:\nパラメータ名称がマッチしない内容を渡した場合\nコンテナに追加されるのではなく、無視される")
            list(new SampleParam( { a: "A" } ))
        }
        
        private function case6(e: MouseEvent = null): void {
            init("test case 6:\n型が異なるオブジェクトを渡された場合はエラー\nこの例外制御は呼出側に任せる")
            try {
                list(new SampleParam( { head: new Object() } ))
            } catch (ex: TypeError) {
                memo.appendText("\n" + ex.message)
            }
        }
    }
}

// --------------------------------------------------
// 基底パラメータコンテナクラス (Abstract) : 継承時 コンストラクタで super(this, obj) を呼ぶこと
class BaseParamContainer { 
    private function inject(o: Object): void {
        for (var n: String in o) if (this.hasOwnProperty(n)) this[n] = o[n]
    }
    
    public function BaseParamContainer(access:*= null, obj: Object = null) {
        if (access != this) throw new Error("AbstractException")
        inject(obj)
    }
}
// --------------------------------------------------

// サンプル パラメータクラス
import flash.display.DisplayObject;
class SampleParam extends BaseParamContainer {
   
    // inject するためパラメータは public とすること (カプセル化を壊すが利便性を優先)
    public var tail: DisplayObject
    public var head: DisplayObject
    public var lineWidth: uint = 1
    public var lineColor: uint = 0x000000
    public var fillColor: uint = 0x000000
    public var fill: Boolean = false
    
    // factory method sample : 若干異なるパラメータで生成したい場合に利用
    public static function create(obj: Object = null): SampleParam {
        var result: SampleParam = new SampleParam(obj)
        result.lineWidth = 2;
        result.lineColor = 0xFF0000;
        return result
    }
    
    // コンストラクタでは必ず super() を適切に呼ぶこと
    public function SampleParam(obj: Object = null) { super(this, obj) }
}