Core Languageの最近のブログ記事

Flash Professional CS5 と Flex SDK 4 から、初期値を指定して Vector を初期化できるようになりました。これはコンパイラーの仕様変更です。

いくつかの型では、既に、インスタンスを生成する際に 3 種類の手段、初期値の指定、コンストラクターの使用、グローバル関数の使用、を利用することができました。例えば、配列の場合は以下のようにしてインスタンスを生成することができます。

// 初期値を [] 内に指定
var arr1:Array = ["a", "b", "c"];
 
// コンストラクターを使用
var arr2:Array = new Array("a", "b", "c");
 
// グローバル関数を使用
var obj:Object = ["a", "b", "c"];
var arr3:Array = Array(obj);
 

(注:上の例の arr3 は、最初の要素に obj を持つ配列になります。つまり、arr3 は配列の配列です。ということで、この場合 Array() グローバル関数はキャストとしては使えません。Array 型で、キャストが目的のときには as 演算子を使用します。var arr3:Array = obj as Array; )

Vector のインスタンス生成手段は、いままではコンストラクターもしくはグローバル関数のどちらかでした。CS5 & Flex 4 からは、初期値を直接指定する構文が使えます。

Vector の初期化子指定

Vector は、配列と違って格納できる型が決まっています。そのため、Vector 型の属性宣言をする際、要素として持つオブジェクトの型も一緒に指定します。例えば、String を要素として持つ Vector 属性の宣言は下のように記述します。

前回に引き続き変数宣言の有無による違いを少し追求してみたいと思います。今回はパフォーマンスの違いについてです。よく知られている話だとは思いますがいちおう。

変数宣言の有無とパフォーマンス

まずは、以下のコードを考えます。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 程短縮されています。

ちょっと前の記事 (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);
  }
}
 

継承の話題の続きです。

インスタンスメソッドのオーバーライド

継承したクラスのインスタンスメソッドをオーバーライドするには override キーワードを使います。オーバーライドするメソッドは以下の条件を満たす必要があります。

  • 同じ名前である
  • 同じアクセス修飾子である
  • 同じ数の引数を持つ
  • 個々の引数の型が同じである
  • 戻り値の型が同じである

おくればせながら、継承に関する話題を少しまとめます。

extends

サブクラスを定義するには extends キーワードを使います。

// 親クラスの定義
public class MyBase 
{
  public function hello():String {
    return "hello";
  }
}
// サブクラスの定義
public class MySub extends MyBase
{
}

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";
}

今回は AS3 のthis と Java の this はよく似ているという話です。

ActionScript のようなプロトタイプベースの言語では、this の扱いが少々分かりにくくなります。 たとえば以下のような例を考えて見ましょう。

Flex2 のベータ1からインスタンス変数の宣言に prototype 修飾子を使用することができるようになりました。例えば、以下の例では pProp という変数に prototype 修飾子が定義されています。

public class ProtoSample {
  public prototype var pProp:int = 10;
}

Cairngorm 2.0 アルファも公開されました。(こちらです

さて、Flex2 のベータ1では Player API や言語レベルでの変更が行われています。このため、アルファ版で作成したコードは一部修正の必要があるケースがあります。今回は、変更された箇所の中から今までの記事に関連する項目をお伝えします。

クラスには静的なプロパティとインスタンスプロパティを定義することができます。インスタンスプロパティはその名のとおりインスタンス毎に存在するプロパティですが、静的プロパティはインスタンスと関連付けられることは無く、代わりにクラスに一つだけ存在するクラスオブジェクトと結び付けられます。

AS2 では、パフォーマンスの観点からインターフェースの使用は控えるべきと言われていました。が、AS3 からはようやくその恩恵に与ることができそうです。実際、Flex2 のフレームワークでもインターフェースが多用されています。

インターフェースの定義

インターフェースは公開するメソッドの集合としての型を定義するのに使います。例えば、こんな感じです。

今回は、関数に関連するタームの整理です。

  1. Function
    ActionScript では関数もプロパティの一種ですが、関数として認識されるオブジェクトの型の名前が Function です。Function 型のオブジェクトは引数を渡して処理を呼び出すことができます。
  2. 関数
    Function 型のオブジェクトの定義やそのインスタンス全般を指します。
  3. メソッド
    クラス定義の一部としてある関数定義や実行時にオブジェクトから呼び出し可能な関数オブジェクトを指します。別の見方をすると、クラス定義の外で定義される関数やオブジェクトから呼び出すことのできない状態の関数が有るということになります。

それでは、皆様良いお年を。

コンストラクタはクラス名と同じ名前を持つ関数で、インスタンスを初期化する際に呼び出されます。コンストラクタは初期化時の定型処理を記述するのに使われますが、特に定義されていなくても文法上の問題は有りません。

class SampleClass {
  // コンストラクタ定義
  public function SampleClass() {
    // 初期化処理の記述
  }
}

get と set は特別な関数を定義するために予約されている名前です。オブジェクトのカプセル化のため属性に直接アクセスする代わりに関数を定義したい、という人のための機能です。 他の言語では getXXX() とか setXXX() とかいう関数を定義したりすると思いますが、ActionScript では少し流儀が異なります。

下が、get 関数と set 関数それぞれを定義しているサンプルです。

引数のデフォルト値

AS3 では関数宣言時に引数のデフォルト値を指定することができます。デフォルト値の無い引数と有る引数が存在する場合には、デフォルト値の無い引数を引数の列の最初にまとめます。デフォルト値として使用できる値は、コンパイル時に既知の定数のみです。

function sampFunc(x:int, y:int, z:int = 1) {
  // 呼び出し時に指定がなければ z の値は 1 になる
}
sampFunc(1, 0);

デフォルト値のある引数は呼び出し時に省略可能になります。通常は意識する必要のない引数に使用するとよいでしょう。

ActionScript のオブジェクトは Java や C++ と少し違う点があります。それは、オブジェクトがプロパティの集合であるという点です。プロパティには関数も含まれます。そのため実行時に関数を代入することも可能です。また、関数も他のオブジェクトと同様に、固有のプロパティをやメソッドを持つことができます。

AS2 でも package の機能はありましたが、その役割は基本的にクラス名の重複を防ぐことでした。AS3 の package はアクセススコープの単位にもなります。

package とアクセス修飾子

AS3 では以下のようにして定義するクラスが含まれるパッケージ名を宣言します。以下の例では、sample パッケージ内に SampleClass クラスを定義しています。このときクラスの完全限定名は sample.SampleClass になります。

package sample {
  import othersample.OtherClass;
  class SampleClass {
    function sampleFunction() {}
  }
}

ActionScript3 は動的言語ですので、実行時につじつまが合えば型の指定は省いても構わない、という記述方法が可能です。とりあえず単純な例としては、

var forDebug; // 型指定なしの宣言
forDebug = 0; // 数値を代入 trace(forDebug);
forDebug = "1"; // 文字列を代入 trace(forDebug);

2014年1月

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
レンタルサーバー

月別 アーカイブ

Powered by Movable Type 4.261