akihiro kamijo: May 2006 Archives

« April 2006 | Main | June 2006 »

May 31, 2006

Number

Number (livedocs@lab) は整数や浮動小数点数を表すことのできる型です。Number のオブジェクトは IEEE-754 に定義される 64-bit の倍精度のフォーマットで約 4.94e-324 から 1.80e+308 の値を正負それぞれの領域で表すことができます。このため int や uint ではカバーできない数値も扱うことができます。

正確な最大値/最小値は以下のとおり定義されています。

Number.MAX_VALUE // 正の数の最大値
Number.MIN_VALUE // 正の数の最小値

Number オブジェクトは toString() メソッドを使って文字列に変換できます。Number クラスでも引数に基数を指定することができます。が、指定した場合は小数部が無視されます。

var myNum:Number = 9.5;
trace(myNum.toString()); // 9.5 が出力される
trace(myNum.toString(2)); // 1001 が出力される
trace(myNum.toString(16)); // 9 が出力される

toFixed() メソッド

toFixed() メソッドは Number オブジェクトの持つ値を小数点数で表現した文字列として返します。引数には小数点以下の有効な桁数を指定します。指定できる範囲は 0 から 20 です。

var num1:Number = 7.31843;
trace(num1.toFixed(2)); // 7.32 が出力される
var num2:Number = 4;
trace(num2.toFixed(2)); // 4.00 が出力される

指定された桁数分の小数部が無い値には必要な数だけ 0 が追加されます。

toExponential() メソッド

toExponential() メソッドは Number オブジェクトの持つ値を指数形式で表した文字列として返します。toFixed() と同じように引数には小数点以下の有効な桁数を指定します。指定できる範囲はこっちも 0 から 20 です。

var num1:Number = 731843;
trace(num1.toExponential(2)); // 7.31e+5 が出力される
var num2:Number = 4;
trace(num2.toExponential(2)); // 4.00 が出力される
var num1:Number = 0.731843;
trace(num1.toExponential(2)); // 7.31e-1 が出力される

0 から 10 の間の数値には e+0 とかがついたりはしないようです。

toPrecision() メソッド

toPrecision() メソッドは Number オブジェクトの持つ値を指定した有効桁数の文字列に変換します。戻り値は小数の場合も指数形式の場合もあります。引数の範囲は 1 から 21 です。

var num1:Number = 73.1843;
trace(num1.toPrecision(3)); // 73.1 が出力される
var num2:Number = 4000;
trace(num2.toPrecision(3)); // 4.00e+3 が出力される

Number() 関数

Number() (livedocs@lab)はプリミティブ型の値を浮動小数点数に変換するグローバル関数です。

trace(Number("")); // 0 が出力される
trace(Number(" 2.4")); // 2.4 が出力される
trace(Number("2.a")); // NaN が出力される

int() や uint() と違い数字で無い文字を含む文字列は NaN になります。

Posted by ackie at 06:23 PM | Comments (0)

May 30, 2006

int と uint

int 型と uint 型

int (livedocs@lab) と uint (livedocs@lab) はそれぞれ 32 ビットの符号付/符号無し整数を表す型です。

表現できる範囲は int が -2,147,483,648 から 2,147,483,647、uint が 0 から 4,294,967,295 です。この範囲で足りない場合には Number を使うことになります。int/uint を使用したほうが Number よりも演算速度は速いため int/uint で用が足りる場合はこちらを選ぶのがよさそうです。

さて、int/uint それぞれの最大値と最小値は以下のように定義されています。

int.MAX_VALUE // int の最大値
int.MIN_VALUE // int の最小値
uint.MAX_VALUE // uint の最大値
uint.MIN_VALUE // uint の最小値

この記述の仕方からも推測できるように int/uint ともに小文字で始まっていますがクラスです。そのため以下のような記述も可能です。

var myInt:int = 1234;
trace(myInt.toString()); // 1234 が出力される
// さすがに以下の記述はむり
// trace(1234.toString());  コンパイルエラー

toString() メソッドには引数に文字列変換する際の基数を指定することもできます。基数の範囲は 2 から 32 です。

var myUint:uint = 9;
trace(myUint.toString(2)); // 1001 が出力される
trace(myUint.toString(8)); // 11 が出力される

コンストラクタを使用てオブジェクトを生成したり、オブジェクトからプリミティブ値(ちょっと定義が変ですが)を取り出したりすることもできます。

var num:int = new int(2);
trace(num.valueOf()); // 2 が出力される

RGBA 値(RGB とアルファ値)を指定する場合には uint を使う必要があります。AS2 に慣れた方はご注意を。

int() 関数 / uint() 関数

int() (livedocs@lab) と uint() (livedocs@lab) はプリミティブ型(Boolean、null、Number、String、undefined)の値を符号付または符号無しの整数に変換するグローバル関数です。

trace(int(1.2)); // 1 が出力される
trace(int(true)); // 1 が出力される
trace(int(false)); // 0 が出力される
trace(int("")); // 0 が出力される
trace(int(" 2")); // 2 が出力される
trace(int("2a")); // 0 が出力される

数字以外の文字を含む文字列は 0 になります。

parseInt() 関数

上記の int() を使っても文字列を int に変換できましたが、parseInt() 関数 (livedocs@lab) を使うと変換時の基数を指定することができます。基数は省略可能です。

trace(parseInt("100")); // 100 が出力される
trace(parseInt("100", 16)); // 256 が出力される
trace(parseInt("100X", 16)); // 256 が出力される

parseInt() は引数の文字列が数字で始まっていれば、変換できるところまで変換した値を返します。

0x で始まる数値は16進数として扱われます。AS2 と違い 0 で始まる数値は8進数として扱われません。

trace(parseInt("0x100")); // 256 が出力される
trace(parseInt("0100")); // 100 が出力される

parseFloat() 関数

浮動小数点数が必要な場合は parseFloat() 関数 (livedocs@lab) を使用します。

trace(parseFloat("100.1")); // 100.1 が出力される

こちらは基数を指定したり 0x で始まる文字列を使うことはできません。

Posted by ackie at 08:20 PM | Comments (0)

May 24, 2006

Flash 次期バージョンについて

今週は Mike Downey が来日しています。次期バージョンの Flash について少し聞くことができたので載せておきます。ただし、あくまでも予定であることはご了承ください。

まず、発売時期については来年の春頃を予定しているようです。日本語版は例によってそのちょっと後くらいという感じでしょうか。Intel Mac 対応もそのタイミングになりそうな雰囲気でした。

やはりというか CS にはバンドルされるようです。ということもあって、目玉の一つは Illustrator, Photoshop, After Effects といった製品とのワークフローの改善だそうです。ちょっと楽しみですね。

ターゲットとなるプレーヤーは Flash Player 9 とのことですので、Flash 史上初めて、オーサリングの発売時に最新の Player が既にある程度のシェアを持っている状態になりそうです。

それに先立って、Flash Player 9 のリリースのタイミングで、Adobe Labs に Flash のパブリックアルファ版が公開される予定です。基本的に、現バージョンに AS3 のサポートを追加しただけのものとのことで、商用目的での使用はできません(そもそも製品でもありません)。また、英語版のみが公開される予定とのことです。

このパブリックアルファ版を使用するには Flash Professional 8 / Studio 8 の登録が必要です。Flash 8 と同時に起動して使用することもできると言っておりました。

Posted by ackie at 04:55 PM | Comments (0)

May 23, 2006

アメリカの番組配信サービスのお話

ふと気がつくと、アメリカの3大ネットワークでは ABC を皮切りに自社サイトで Flash ビデオを使った番組の無料配信が始まっているようです。特に、先行する ABC のサイトは充実していて、主な番組についてはシーズン中のエピソード全てが(たぶん 500kbps くらいで)選び放題&見放題になっています。

この話のみそは、ビデオを視聴する際に必ず広告も見る必要があることで、例えば ABC のケースだと、通常の TV 放送と同様に番組中に3つの CM が入っていて、CM の後の箇所を見るためには必ずその CM を見なければなりません。最後の場面をクリックして番組の途中を飛ばすこともできますが、CM はスキップすることができません。そのため、エピソードを終わりまで見ると必ず3つの CM を見ることになるわけです。

この例に見られるのはコンテンツ課金から広告収入へのビジネスモデルの変更です。そして、それを可能にしているのが Flash Media Server と Flash player というわけです。

アメリカでは同様のサービスが急速に増えつつあるようですが、HD レコーダーの普及で CM のスキップが問題になったりする中で、インターネットで広告によるビジネスが成り立つというのが面白いですね。果たして日本ではどうでしょうか。

(残念ながら US の IP アドレスから出ないと視聴できないようですが)ABC のサイトはこちらです。(ABC.com: Full Episode Streaming

Posted by ackie at 11:51 PM | Comments (0)

May 18, 2006

describeType メソッド

describeType() メソッド (livedocs@lab) は引数に渡されたオブジェクトの情報を XML 形式で返します。引数には ActionScript の任意のオブジェクトを(クラスや int なども)渡すことができます。

var mc:MovieClip = new MovieClip();
var typeInfo:XML = describeType(mc);

返される XML オブジェクトに含まれる情報は引数として渡されたオブジェクトの属性やメソッド等です。Java のリフレクションと同じような機能です。

XML オブジェクトだと扱いが面倒に思われるかもしれませんが、E4X のおかげでむしろ Object よりも便利です。例えば、上の例の続きで、戻り値が void のメソッドのリストを取得するには typeInfo.method.(@returnType == "void") のように記述できます。

出力例

以下、MovieClip のインスタンスを describeType() に渡した結果を例として具体的な出力を説明します。

まず、ルートノードは type というタグです。type タグの属性を見ると、パッケージ名とクラス名、親クラス名、その他のクラス宣言時の修飾子が分かります。

<type name="flash.display::MovieClip" base="flash.display::Sprite" isDynamic="true" isFinal="false" isStatic="false">  

残りのタグは、type の子ノードです。一つ目は extendsClass タグで、継承関係にある全ての上位クラスの名前とパッケージ名が type 属性から分かります。また implementsInterface タグで継承しているインターフェースも分かります。

<extendsClass type="flash.display::Sprite"/>
<extendsClass type="flash.display::DisplayObjectContainer"/>
<extendsClass type="flash.display::InteractiveObject"/>
<extendsClass type="flash.display::DisplayObject"/>
<extendsClass type="flash.events::EventDispatcher"/>
<extendsClass type="Object"/>
<implementsInterface type="flash.display::IBitmapDrawable"/>
<implementsInterface type="flash.events::IEventDispatcher"/>

属性情報は accessor タグから分かります。名前と、アクセス、型、宣言されたクラスが分かります。

<accessor name="totalFrames" access="readonly" type="int" declaredBy="flash.display::MovieClip"/>
<accessor name="currentFrame" access="readonly" type="int" declaredBy="flash.display::MovieClip"/>

メソッド情報は method タグです。メソッド名、宣言したクラス、戻り値の型が属性に記述されます。パラメータを持つメソッドは子ノードを持ち、そこに、順番、型、オプションかどうかの情報があります。

<method name="play" declaredBy="flash.display::MovieClip" returnType="void"/>
<method name="gotoAndPlay" declaredBy="flash.display::MovieClip" returnType="void">
  <parameter index="1" type="*" optional="false"/>
  <parameter index="2" type="String" optional="true"/>
</method>

一通り MovieClip の定義情報が終わると、上位クラスで宣言されている属性とメソッドが続きます。MovieClip の場合は Sprite から EventDispatcher まで長々と情報が表示されます。

<method name="startDrag" declaredBy="flash.display::Sprite" returnType="void">
<parameter index="1" type="Boolean" optional="true"/>
<parameter index="2" type="flash.geom::Rectangle" optional="true"/>
</method>
...
...
<method name="addEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
<parameter index="4" type="int" optional="true"/>
<parameter index="5" type="Boolean" optional="true"/>
</method>

静的情報の取得

上の例ではインスタンスの情報のみで、クラスメソッド等の情報は出てきませんでした。static 宣言されている情報を取得するには describeType() にクラスオブジェクトを渡します。

下の例では Font クラスオブジェクトを渡しています。

trace(describeType(Font));

この例での出力は以下のようになります。type タグの base 属性が Class になっています。その他の属性も、クラスオブジェクトに対するもので Font クラスの属性ではありません。

type タグの直接の子ノードになっている method や accessor タグが static 宣言されたものです。インスタンス変数やメソッドは factory タグの子ノードになっています。

<type name="flash.text::Font" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <method name="enumerate" declaredBy="flash.display::Font" returnType="Array"/>
  <method name="register" declaredBy="flash.display::Font" returnType="void">
    <parameter index="1" type="Class" optional="false"/>
  </method>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="flash.text::Font">
    <extendsClass type="Object"/>
    <accessor name="fontStyle" access="readonly" type="String" declaredBy="flash.text::Font"/>
    <accessor name="fontName" access="readonly" type="String" declaredBy="flash.text::Font"/>
    <method name="hasGlyphs" declaredBy="flash.text::Font" returnType="Boolean">
      <parameter index="1" type="String" optional="false"/>
    </method>
  </factory>
</type>

beta3 ではメタタグ情報が出力されないようで、使用変更というよりはバグっぽい感じです。

Posted by ackie at 06:50 PM | Comments (0)

May 17, 2006

Dictionary クラス(前の続き)

ようやく new Dictionary() が実行できるようになったので続きです。

weak-value ディクショナリー

以前の記事に書いたように、Dictionary クラスは weak-key ディクショナリーの機能を持っています。キーオブジェクトへの参照が弱い参照のため、使われなくなったキーとそのエントリーを自動的に開放するという使い方ができます。

一方、値として管理されているオブジェクトがしばらく参照されなかったら自動的に開放するという使い方はできません。

このようなケースは(本来であれば) weak-value ディクショナリーを使う場面です。weak-value ディクショナリーでは値オブジェクトへの参照が弱い参照のため、他から参照されていない値オブジェクトはガーベッジコレクションの対象になります。

さて、現状で weak-value ディクショナリーを実現するには Dictionary のキーと値の扱いを入れ替えてしまうのが簡単そうです。Proxy を使うと以下の用に実現できます。

public dynamic class MyDictionary extends Proxy {
  private var _dict:Object;
  public function MyDictionary() {
    _dict = new Dictionary(true);
  }
  override flash_proxy function setProperty(name:*, value:*):void {
    // 値とキーを逆にしてエントリーを追加
    _dict[value] = name;
  }
}

本来キーとして使われるオブジェクトを値として格納したので、取り出す際には一つ一つ調べることになります。

override flash_proxy function getProperty(name:*):* {
  for (var value:* in _dict) {
    if (_dict[value] == name) {
      return value;
    }
  }
}

ただこの方法ではエントリーが多くなるに連れ参照時のパフォーマンスが悪くなりそうです。

そこで、ちょっと贅沢ですがエントリーごとに Dictionary を生成するようにしてみます。

override flash_proxy function setProperty(name:*, value:*):void {
  // エントリ専用の Dictionary オブジェクト生成
  var dict4Val:Dictionary = new Dictionary(true);
  // 値とキーを逆にしてエントリーを追加
  dict4Val[value] = name;
  // Dictionary オブジェクトを値として設定
  _dict[name] = dict4Val;
}

今回は Dictionary が一つしかエントリを持たないため、取り出す際は最初に見つかったものをそのまま返すことができます。

override flash_proxy function getProperty(name:*):* {
  // まず対応する Dictionary オブジェクトを取り出す
  var dict4Val:Dictionary = _dict[name];
  // dict4Val は一つしかキーを持たないはず
  for (var value:* in dict4Val) {
    // 見つかった値を返す
    return value;
  }
}

Posted by ackie at 06:18 PM | Comments (0)

May 15, 2006

dynamic クラス

Dreamweaver 8.0.2 アップデータが公開されました。IE のアクティブコンテンツ関連の変更に対応します。ダウンロードはこちらです。(Dreamweaver 8.0.2 アップデータ

さて、遅ればせながら、前の記事のフォローということで。

ダイナミック(dynamic)クラス

AS3 のクラスはコンパイル時に属性が決定されるのが基本ですが、ダイナミッククラスとして宣言すると実行時に属性や関数を定義することができます。

ダイナミッククラスにするにはクラス定義に dynamic 属性を付けます。

public dynamic class FooDynamic {
  private var privProp:String = "private property";
  public var pubProp:String = "public property";
}

上記の FooDynamic のインスタンスを作成すると属性や関数定義を追加することができます。例えば、以下の例では属性と関数を追加しています。

var foo:FooDynamic = new FooDynamic();
foo.dynamicProp = "foo";
foo.dynamicFunc = function():String { return "foo"; };

ダイナミッククラスは動的に属性が追加できるため、コンパイル時に存在しない属性への参照が見つかってもエラーにはなりません。また、実行時でも、存在しない属性への参照は undefined の値となりリファレンスエラーにはなりません。

とはいえ、実行時に存在しない関数を呼び出そうとするとさすがにリファレンスエラーになります。

var foo:FooDynamic = new FooDynamic();
trace(foo.nonProp); // undefined が出力される
foo.nonFunc(); // リファレンスエラーになる

ところで、動的に追加された関数からは private な属性や関数にアクセスすることができません。public な属性や関数へのアクセスは可能ですが、明示的に this またはオブジェクトを指定することが必要です。

var foo:FooDynamic = new FooDynamic();
foo.traceProperties = function():void {
  trace(this.privProp); // undefined が出力される(存在しない属性として扱われる)
  trace(this.pubProp); // public property が出力される
}
foo.traceProperties();

上の例は FooDynamic クラスに traceProperties() メソッドを追加して private/public それぞれの属性を参照しています。

ちなみに、追加する際に private 宣言されている属性や関数と同じ名前を使ってもエラーにはなりません。別の定義として扱われるためです。

Posted by ackie at 09:22 PM | Comments (0)

May 12, 2006

* (アスタリスク)と void と Null

AS3 のオブジェクトは基本的には Object 型(またはそのサブクラス)で表されますが、例外となる型が3つあります。今回はその3つの紹介です。

* (アスタリスク)

* は「型指定なし」という型情報を指定するときに使います。つまり型の指定を省略したときと同じになります。

public var foo:*; // 型指定なし
public var bar;  // こちらも * と同じ扱い

だとすると * なんて付けない方が楽そうですが、何も無いと、こんどは付け忘れたのか本当に型指定を省略したかったのかが分からなくなってしまいます。ですので、きっちりとコードを書くのが趣味の人は * を、型なんてそもそも気にする気の無い人は何も無しを選択するのがよいでしょう。

「型指定なし」で宣言した変数には、コンパイル時に型チェックが起きません(当たり前ですが)。そのため、とりあえずエラーが出るまでは使っちゃおう、というずぼらな使い方ができます。動的言語ならではの使い方ですね。

ただし、実行時には何らかの値をもつわけですから、いずれにせよ実行時には型チェックが行われます。

また、型指定なしにすると Object 型では使用できない値、すなわち undefined を使うことができます。

void

void が持つ値は一つだけで undefined です。void は関数の戻り値を指定する際にしか使用できません。

public function foo():void {
  // return なし
}

戻り値がそもそも存在しないので値が undefined というわけです。

Null

Null が持つ値も一つだけで null です。Null はクラスと関連付けられていないため、変数等の型指定には使用できません。

null は Object 型への参照が値を持たないことを示します。初期化されていない Object 型の変数への参照は null になります。

null と比較すると undefined は値だけでなく型情報もないことを示す値であることが分かると思います。

例えば dynamic クラスで、存在しない属性を参照したときの値も undefined です(この場合も型情報のない点が共通になっています)。このように AS3 のような動的に属性の追加できる言語では null と undefined を区別できることが役立つケースもあるわけです。

Object と Null と void を合わせると AS3 の全ての値を持つことができます。

Posted by ackie at 06:42 PM | Comments (0)

May 11, 2006

Spry (Ajax フレームワーク)公開

Adobe から Spry という名前の Ajax フレームワークが公開されました。(Adobe Labs/spry) Spry は BSD ライセンスの下でフリーで使用できます。

こちらのページでデモが見られます。(Spry Demos) ダウンロードはこちらから。(Spry Download

Spry の特徴は Web 制作者を主ターゲットにしていることで、CSS を使った HTML ページ作成の知識があれば、特に JavaScript に詳しくなくても使えるよう設計されています。このようにすることで、従来の Web デザインの延長として Ajax を使えるようにしたいというのが目標です。今までの Ajax はどちらかというとプログラマの視点から語られることが多かったですよね。

既に公開されている Flex-Ajax Bridge (FABridge) と組み合わせれば Spry と Flex 2.0 を組み合わせて使うこともできます。Google Finance (例:NASDAC 情報のページ)のようなサイトがぐっと作りやすくなるわけです。

今回のリリースはまだプレビュー版といった位置づけですが、今後だんだんと充実してくることと思いますのでご期待ください。

Posted by ackie at 10:02 AM | Comments (3)

May 09, 2006

Flex2 beta3 リリース

Flex 2.0 のベータ 3 が Adobe Labs にて公開されました。先日もお伝えしたように Flash Player のバージョンが 9 になっていますが、AS3 関連の変更点は API の名前の整合性を取るためのものがほとんどで、今までのように機能レベルでの変更は見当たりません。ようやく仕様も固まった感じです。

ダウンロードはこちらから。(Adobe Labs - Flex 2.0

Posted by ackie at 09:56 AM | Comments (0)