« June 2007 | Main | August 2007 »
July 31, 2007
Adobe Flash Ajax Video (FAVideo) コンポーネント
新しく Adobe Flash Ajax Video (FAVideo) コンポーネントが Adobe Labs に公開されました。(Flash-Ajax Video Component@Labs) FAVideo は Ajax アプリケーションから Flash ビデオを利用するためのコンポーネントで、JavaScript からビデオの表示位置や大きさを指定したり再生をコントロールすることができます。Flash Player 8 以降がインストールされている環境であればビデオを表示できるようになります。
FAVideo コンポーネントはソースコードが BSD ライセンスの元で (Flash-Ajax Video Component:License) 公開されています。サンプルを含む zip ファイルが Labs よりダウンロードできます。 ( favideo_072707.zip : 2.19MB - FAVideo コンポーネント自体は 15KB 程です。念のため。)
使い方は、下の一行を追加して、
<script src="FAVideo.js" type="text/javascript"></script>
スクリプトブロック内で、下のように記述します。
videoPlayer = new FAVideo("id", "name.flv");
スキンの変更も可能です。Dreamweaver に Flash ビデオ埋め込み機能がありますが、これと同じようなものだと考えてよさそうです。
Posted by ackie at 04:58 PM | Comments (0)
July 27, 2007
SWF と FLV のバージョン 9 ファイルフォーマット公開
SWF と FLV のバージョン 9 ファイルフォーマットがようやく公開されました。こちらの URL からライセンス契約を行うと入手できます。 (Adobe Player Licensing)
このライセンスは SWF を生成するソフトウェアの開発を支援するためのもので、SWF を実行するソフトウェアの開発には利用できません。一応念のため。
Posted by ackie at 06:01 PM | Comments (4)
July 23, 2007
Flex 2.0.1 Hotfix 3
Flex 2.0.1 SDK Hotfix 3 が US のサポートページに公開されていますのでお知らせします。
まだ日本では発表されていませんが、US で一緒に発表された LCDS 2.5.1 を利用する際は Flex Builder 2.0.1 に Hotfix 3 を適用する必要があります。将来 LCDS 2.5.1 を採用するプロジェクトがあれば、ご面倒でも Hotfix 3 の件は忘れずにご対応ください。逆に、Hotfix 3 は LCDS 2.5.1 との使用が基本です。サーバ側に FDS 2.0.1 をご使用の場合はご注意ください。
そのほかの注意事項としては以下のものがあります。
- Flex Builder 2.0 はサポートされません
- Hotfix 3 を適用する前に Hotfix 2 を適用する必要があります
- Hotfix で修正されている件に該当する問題が起きていない場合は適用をお勧めしません
インストール手順などの詳細は以下のテックノートをご覧ください。
Posted by ackie at 11:26 AM | Comments (0)
July 18, 2007
Flash Player 9 セキュリティアップデート
すでにいくつかのニュースやサイトで紹介されていますが、先週 Flash Player のアップデーターが公開されました。今回のアップデートはいくつかのセキュリティ上の脆弱性に対応するためのものです。
既存のバージョンは基本的に今回のアップデートで対応された問題の対象になります (Flash Player 9.0.45.0 以前、8.0.34.0 以前、7.0.69.0 以前) ので、最新版の 9.0.47.0 (Linux は 9.0.48.0) にアップデートすることをお勧めします。ダウンロードは Flash Player ダウンロードセンター (Player Download Center) から行えます。
Flash Player 9 がサポートしないプラットフォーム用に Flash Player 7 の対応版 (7.0.70.0) も公開されています。ダウンロードは US のサポートページからどうぞ。(Flash Player upgrade for operating systems that do not support Flash Player 8)
その他にスタンドアローンプレーヤやオーサリング環境用のアップデートも公開されています。それぞれバージョンごとに以下のアップデートが用意されています。こちらもダウンロードは US のサポートページからお願いします。(Adobe Flash Player Support Center)
Flash Player 9
- Flash CS3 用アップデート
- デバッグプレーヤ (FlexBuilder 2 向け)
- スタンドアローンプレーヤ
Flash Player 8
- Flash 8 用アップデート
- Mac 用スタンドアローンプレーヤ
Flash Player 7
- Mac 用スタンドアローンプレーヤ
Posted by ackie at 05:22 PM | Comments (3)
July 12, 2007
== 演算子と暗黙の型変換
前回の続きです。なぜ "" == foo が true と評価されるのか、まず、暗黙の型変換が行われる際のルールを一つ確認します。
暗黙の型変換の基準
暗黙の型変換が行われる際の基準となる型は、変数に関連付けられた型注釈ではなく、値であるオブジェクト自体の型です。ですので変数の型に注目していても暗黙の型変換の結果は分かりません。
例えば、今回問題になっている例 foo:Object = 0 では、値である 0 の型が暗黙の型変換の基準になります。foo の型ではありません。そのため if 文の条件は文字列とと数値の比較として扱われます。
var foo:Object = 0;
if ("" == foo) { // 実際には "" == 0 が評価される
trace("foo is null String");
}
そうすると、今回のケースでは "" と 0 が等価であるかどうかが評価されていることになります。
== 実行時の暗黙の型変換のルール
さて、文字列と数値を == で評価する際には、「文字列を数値に変換してから比較する」というルールが適用されます。そのため、まず空文字列から数値への変換が行われます。
AS3 では数値表現として扱うことのできない文字列を数値に変換した場合の結果は 0 になります。空文字列も意味の有る数値表現ではありませんから数値に型変換されたときの値は 0 です。すると "" == 0 は 0 == 0 となります。これにより if 文は最終的に true になるわけです。
別の例を見てみましょう。今度は空の配列と空文字列を比較するケースです。
var foo:Object = [];
if ("" == foo) {
trace("foo は空文字列です");
}
こちらのケースも ”foo は空文字列です” が表示されます。
ここで適用されたルールは、「文字列と配列を == で評価する場合は配列を文字列に変換してから行う」というものです。空の配列を String 型に変換すると空文字列になるため、上の if 文の条件は "" == "" となり、結果として true になったと考えることができます。
ここまでのまとめ
ここで一旦まとめてみましょう。まず、== 演算子では比較対照のデータ型が異なる場合、暗黙の型変換が行われます。そして、変換のルールは型の組み合わせに応じていくつかのルールの中から選ばれます。
ECMAScript の定義を参照すると == 演算子を実行する前に、適用される暗黙の型変換ルールを決定する 23 ステップ相当の条件チェックが必要であることが分かります。従って == 演算子の結果を正しく予測するには、この 23 ステップを適用した場合に起こりうる全てのケースについて考慮する必要があります。さらに、それぞれのケースについて、「空文字列は 0 に変換される」とか「空の配列は空文字列に変換される」といったルールを全て把握していなければなりません。
これはあまり現実的とはいえませんよね。ということで、ここまでのまとめとしては、
- == 演算子の結果は信用できない
ということになります。
少し AS3 をかばっておくと、これは ECMAScript に準拠したために起きている状況で、AS3 の設計者がみんなを混乱させてやろうとか思った訳では (決して) ありません。
ともあれ、== を使わずにプログラムを書くのも難しいので、プログラムを記述する側で何らかの対応をすることが必要になります。次はその対応方法を考えてみたいと思います。
Posted by ackie at 06:48 PM | Comments (0)
July 09, 2007
AS3 の変数の型に関連する話
今回は AS3 の型システムの特徴についての話です。strict モードの人には関係ない話が続きましたが、ここからはコンパイラの環境設定に依存しない話題です(たぶん)。
まず、下のコードについて考えてみます。 オブジェクト型の変数 foo に数値の 0 を代入して空文字列と比較しています。
var foo:Object = 0;
if ("" == foo) {
trace("foo は空文字列です");
}
上の If 文は空文字を検出するためのものに見えますが、実際にはこれを実行すると ”foo は空文字列です” が表示されます。
この結果は予想通りだったでしょうか?想定外だった人はこの先を。
上記の結果は、AS3 が弱い型の性質を持っているために起こります。AS3 では ’+’ 等のオペレータに対して複数のデータ型が混在すると処理の前に暗黙の型変換が行われます。これによって例えば trace("count:" + 0) のように文字列と数値を”足して”もそれらしい結果を得ることができるわけです。
暗黙の型変換は上の trace() の例のようにしばしば便利な機能として使われますが、一方で予期せぬ結果になるケースもある面倒なものだったりもします。例えば、この記事の最初に挙げた例も暗黙の型変換の結果によるものですが、実際にどのような変換が行われて true と評価されたのかは直感的には理解し難いものです。
ということで、これから上のサンプル内の if 文で実際に起きていたこと、このような結果を避ける方法について話を移そうと思いますが、その前に 2 つほど基礎となる項目の確認です。
int がオブジェクトであること
とりあえず、下のサンプルをみてください。
var foo:int = 0; var bar:String = foo.toString();
2 行目のように int 型の変数のメソッドが呼びだせるということは、AS3 の int は Java でいうと Integer に近いものだということです。ASDoc を見てみると、実際に int が Object のサブクラスであることが確認できます。同様に uint や Number も Object のサブクラスです (Number はクラス名っぽいですね)。
このため冒頭の例でも Object 型の変数に数値を代入することができたわけです。
ちなみに下の 2 行はプログラムの意味的には同じになります。もちろん動的な属性を持たない int 型のオブジェクトのコンストラクタをわざわざ呼ぶ必要はありませんが。
var i:int = 0; var i:int = new int(0);
「型が無い」という型
数値もオブジェクトとして扱われるということで全ての値は Object 型に属するように思えますが、実際は例外があります。Object は undefined を値として持つことができません。undefined が属性値として必要な場合は * を型として指定します。
AS2 では Object 型オブジェクトの初期値は undefind でしたが AS3 では null になっています。* 型の初期値は undefined です。
ところで * は型指定が無いという型(ちょっと矛盾?)です。というわけで、* は型注釈を省略したときに使われる型でもあります。
// 下の2行は同じ意味 var foo; var foo:*;
変数の型を明示的にしない場合 Object 型ではないことに注意しましょう。* 型のオブジェクトは属性やメソッドを持たないため、コンパイル時の型チェックが行われません。
実行時まで型チェックを遅らせられることは動的言語の利点ですが、厳密な型チェックを行う strict モードでも * を使うとこの恩恵にあずかることができます。
ちょっと長くなったので、続きは次回に。
Posted by ackie at 05:46 PM | Comments (0)
July 06, 2007
AS3 での変数宣言とパフォーマンス
前回に引き続き変数宣言の有無による違いを少し追求してみたいと思います。今回はパフォーマンスの違いについてです。よく知られている話だとは思いますがいちおう。
変数宣言の有無とパフォーマンス
まずは、以下のコードを考えます。Date のオブジェクトを生成して getTime() メソッドを 10 万回呼び出しています。変数宣言は行われていません。
date = new Date() for (i=0; i<100000; i++) date.getTime()
手持ちの環境で上のコードを実行してみます。すると、for ループの箇所の実行に約 470ms かかりました。
これを下のように変えてみます。2 行目で var を使った変数宣言を追加しています。それから for ループ内では、2 行目で新しく追加した変数経由でメソッドを呼び出しています。
date = new Date() var dateVar = date // 追加 for (i=0; i<100000; i++) dateVar.getTime()
こちらはループの実行に約 340ms かかりました。処理時間が 130ms 程短縮されています。
for ループ内で参照しているオブジェクトは、どちらのケースも同じく Date のインスタンスです。両者の違いは、参照に使用している変数の宣言に var が付いているかどうかだけです。このことから var 無しの変数からオブジェクトを参照する行為には、ずいぶん余計な時間がかかっていることが分かります。
関数内で var を付けて宣言した変数をローカル変数といいます。上の結果が示すようにこローカル変数へのアクセスは高速です。また、ローカル変数の有効範囲は宣言された関数内のみですので、参照の消し忘れによるメモリリークの心配もありません。
一方、var 無しで変数を使用した場合は、前回見たように、クラス内で有効な一種のグローバル変数になります。上の結果のとおり、グローバル変数へのアクセスはローカル変数より時間がかかります。
型注釈の有無とパフォーマンス
次は、変数宣言に型注釈をつけてみます。2 行目の宣言で明示的に Date 型を指定しています。
date = new Date() var dateTyped:Date = date // 型を指定 for (i=0; i<100000; i++) dateTyped.getTime()
実行してみるとループの箇所に約 300ms かかりました。先程の 340ms と比べ更に一割ほど短縮されています。
これは、AS3 の実行環境が型情報をパフォーマンス向上に役立てる機能を持っているからです。また、型注釈をつけるとメモリの使用量を減らす効果もあります。このような実行環境による型情報のサポートは AS3 の大きな特徴です。(注:この箇所は dynamic なクラスのオブジェクトに動的に追加されたメソッドやプロパティには当てはまりません)
変数宣言の追加とここまでのまとめ
さて、よく見ると、ループ内には i という変数も使われています。これもローカル変数として宣言してみます。
date = new Date() var dateTyped:Date = date for (var i=0; i<100000; i++) // i をローカル変数に dateTyped.getTime()
この結果、約 20ms になりました。i は 2 回使われている分効果が大きいようです。
さらに i に型をつけてみます。
date = new Date() var dateTyped:Date = date for (var i:int=0; i<100000; i++) // i を int 型に dateTyped.getTime()
これで約 13ms になりました。最初の数値である 470ms と比べて 3% 以下になっています。
var とか型とか書くのを習慣にしたほうがよさそう、という結論になりそうですが、10 万回繰り返してやっとこの程度の差という見方もできます。ここでの例のように後から変数宣言を追加すればよい話ですし、パフォーマンスの観点からだけなら、あまり神経質にならなくてもよいかもしれません。特に、型注釈の有り無しによる差はほとんど無いケースも多かったりします。
ただ、前回説明したように、グローバル変数 (var を使った宣言無しの変数) の使用はプログラムの構造を分かりにくくする可能性があります。パフォーマンスの件と併せると、特に理由の無い限り避けた方が賢明そうですね。
そうすると、ここまでのまとめとしては、
- var は基本的に付ける
- 型注釈はあったほうがまし
ということになります。
が、型注釈が無いことでプログラムの実行結果が非常に分かりにくくなる場合があったりします。次はこの点について掘り下げてみようと思います。
Posted by ackie at 06:25 PM | Comments (0)
July 05, 2007
AS3 での変数宣言 (var) の省略について
ちょっと前の記事 (AS3 で動的言語のススメ) に書いたように strict オプションを指定しないことで AS3 の記述の自由度は格段に上がります。とはいえ、”With great power comes great responsibility” の言葉どおり、選択肢が増えた分だけ、コードを記述する側の責任が大きくなることは意識しておく必要があります。
手抜きの書き方を勧めたことに少し責任を感じて、今回は var による変数宣言の有無による変数の振舞いの違いに少し触れてみたいと思います。
var 無し変数の初期化
Flash CS3 でも Flex でも AS3 コンパイラの厳密な型チェックのオプションをオフにすれば var 宣言無しで変数が使用できるようになります。例えば下のコードは問題なくコンパイルできます。
public class Foo
{
public function setMyGlobal(val:int):void
{
i = val;
}
public function printMyGlobal():void
{
trace(i);
}
}
以下のコードを試してみると 10 が出力されます。ちゃんと動作していることが確認できます。
var foo:Foo = new Foo(); foo.setMyGlobal(10); foo.printMyGlobal(); // 10 が出力される
ところが、setMyGlobal() を呼び出さずに printMyGlobal() を呼び出すと、実行時に i が定義されていないというエラーメッセージが出力されます。
var foo:Foo = new Foo(); foo.printMyGlobal(); // ランタイムエラー発生
このことから setMyGlobal() 内で i の初期化が行われていたことが分かります。
public function setMyGlobal(val:int):void
{
i = val; // この行が最初に実行された時点で i が初期化される
}
値を代入するコードの実行が、最初の回に限り変数の初期化も兼ねています。つまり、コードの実行される順番に結果が依存するわけです。
var を使った宣言を行わない場合は初期化のタイミングに注意するようにしましょう。明示的に var を使って宣言した変数であればインスタンス生成時に変数の初期化が行われます。
var 無し変数のスコープ
さて、再び最初に定義したクラス Foo を使って次のコードを実行してみましょう。
var foo1:Foo = new Foo(); var foo2:Foo = new Foo(); foo1.setMyGlobal(10); foo2.printMyGlobal(); // 10 が出力される
そうすると 10 が出力されると思います。foo1 で設定した値が foo2 から参照できていることになります。つまり var を使わずに使用された変数 i はクラスのインスタンス間で共有されているわけです。
var を使わないで変数を初期化するコードを記述するのは、スタティックイニシャライザを記述するようなものだと考えてもよいでしょう。もし、Foo クラスの定義が i をインスタンス変数として定義し忘れたものだったとしたら、ずいぶんと異なる振舞いを記述していることになります。
Flash CS3 の場合なら、ムービークリップのタイムラインに var を付けずに使用している変数があれば、その値は全てのインスタンスで共有されることになるわけです。
コンパイラで厳密な型チェックを行うように指定すれば var 宣言されていない変数はコンパイル時に発見して通知してくれます。AS3 コンパイラの設定がデフォルトで strict モードになっているのはなるほどというところでしょうか。Flash 8 以前の fla を AS3 に設定しなおした場合は strict オプションは選択されていませんのでご注意を。
Posted by ackie at 05:54 PM | Comments (2)
July 03, 2007
grant skinner の Flash CS3 用 Adobe AIR extension
Adobe からの Flash CS3 用 AIR 機能拡張はまだ公開されていませんが、grant skinner が Flash CS3 用の AIR extension を自作して公開してくれました。
試してみたところ、日本語環境でも使えるようですので報告しておきます。grant の blog はこちらです。(Creating AIR Projects with Flash CS3)
7月4日追記:早くもアップデート版が公開されたようです。(Creating AIR Panel for Flash CS3 Updated)
Posted by ackie at 06:25 PM | Comments (0)