構文 - Script Language Edit

Last-modified: 2010-03-24 (水) 22:24:36

このページについて Edit

AngelScript(AS)のスクリプト構文について書きます。
(このページに書かれているサンプルコードの一部はAngelScript公式のドキュメントから転載しています。)

「同等」と「同様」の言葉の使い方ついて Edit

文中で「C++と同等」と「C++と同様」という言葉を使っています。
「C++と同等」は「C++とほぼ同じ」という意味合いで,
「C++と同様」は「C++と全く同じ」という意味合いで使っています。

字句 Edit

コメント Edit

C++と同様に1行コメント,ブロックコメントの2種類が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
 
 
 
 
// 1行コメント
/*
 ブロックコメント
*/

Edit

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
// 10進数表現した整数値
int a = 3; 
 
// 16進数表現した整数値
int b = 0xFFFF;
 
// 64bit浮動小数
double ca = 1.2345;
double cb = 1.2345e10;
 
// 32bit浮動小数
float da = 1.2345f;
float db = 1.2345e10f;
 
// bool値
bool ea = true;
bool eb = false;

Edit

組み込み型 Edit

C++と同等の組み込み型が用意されています。

void
C++と同様に関数の戻り値に型に使います。
bool
C++と同様のもので,true,falseのどちらかの値を持ちます。
整数
下記のタイプが存在します。
型名最小値最大値
int8-128127
int16-3276832767
int
int32
-21474836482147483674
int64-922337720368547758089223372036854775807
uint80255
uint16065535
uint
uint32
04294967295
uint64018446744073709551615
公式のドキュメントによると,パフォーマンスを最適化したいのであれば
32bitより小さい型の値はクラスのメンバ変数など,データを保持するもののみに使用し,
それ以外(ローカル変数,一時変数など)は32bitの型の値を使用したほうがいいようです。
浮動小数
下記のタイプが存在します。
型名値の範囲一番小さい正の値最大桁数
float+/- 3.402823466e+381.175494351e-386
double+/- 1.7976931348623158e+3082.2250738585072014e-30815
公式のドキュメントによりますと,ASではNaN(Not-aNumber)を0x7fc00000で表現しているようです。

配列 Edit

配列の変数は次のように宣言します。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
// int型の配列を宣言
int[] intArray;
 
// int型の配列を3つ宣言
int[] intArrA,intArrB,intArrC;
 
// 何も初期化子を指定しなければ,長さ0の配列を作ります
int[] a; // a.length() == 0
 
// 初期化子に数を指定すると,その数の長さの配列を作ります
int[] b(3); // b.length() == 3
 
// 配列初期化子を指定すると,それがコピーされた配列を作ります。
int[] c = {1,2,3}; // 先頭から1,2,3がコピーされた配列

配列はC++と同様にインデクス式を使ってアクセスします。
また,配列の長さはlength()メソッドにより取得できます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
 
 
-
|
!
int[] a = {0,1,2};
for ( uint i = 0; i < a.length(); ++i )
{
    a[i] += 1;
}

ユーザー定義型 Edit

ユーザー定義型(クラスや列挙型)の変数はC++と同様に宣言することができます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
 
 
 
 
 
 
// objという型のインスタンスが作られる
// デフォルトコンストラクタがあればそれが呼ばれる
obj a;
 
// objの一時変数を作成し,aに代入する
a = obj();

オブジェクトハンドル Edit

オブジェクトハンドルとはC++でいう参照・ポインタにあたるものです。
参照先のオブジェクトは参照カウンタで寿命を管理しているため,「既に破棄されたデータにアクセスする」という不正なデータアクセスはおこりません。
もしnullなオブジェクトハンドルにアクセスしようとしたら例外が発生しスクリプトの実行が止まります。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 
 
 
 
 
 
 
-
|
!
 
obj o;
obj@ a; // a はnullで初期化されます
obj@ b = @o; // oの参照をbに代入します
 
b.ModifyMe(); // o.ModifyMe()と同様のことがおこります
 
if ( a is null ) // nullかどうかチェックしています。
{
  @a = @b; // aにbが参照しているオブジェクトを代入します。この場合,結果的にoの参照が渡されています。
}

文字列 Edit

ASでの文字列は8bitもしくは16bitのデータの配列として扱われます。

ASではC++と同等のエスケープシーケンス文字が用意されています。
下記がエスケープシーケンス文字をまとめた表です。

文字意味
¥00null文字
¥¥92バックスラッシュ
¥'39シングルコーテーション
¥"34ダブルコーテーション
¥n10改行文字 LF
¥r13改行文字 CR
¥t9TAB
¥xFFFF0xFFFF16bitで表した文字
¥uFFFF0xFFFFunicode16bitで表した文字
¥uFFFFFFFF¥0xFFFFFFFFunicode32bitで表した文字

文字列はダブルコーテーションもしくはシングルコーテーション(要オプション設定)で囲んで表します。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
 
 
 
 
 
 
 
 
// ダブルコーテーションで囲む例
// 文字列の中にダブルコーテーションを使いたいときは,エスケープ文字を使うこと。
string str1 = "This is a string with \"escape sequences\".";
 
// シングルコーテーションで囲む例
// シングルコーテーションで囲むと,エスケープ文字を使わずに文中にダブルコーテーションを使うことができる
string str2 = 'If single quotes are used then double quotes can be included without "escape sequences".';

C++と同様に複数の文字列を1つの文字列として連結することができます。

すべてを展開すべてを収束
  1
  2
  3
 
 
 
// strには "First Line.¥nSecondLine.¥n"が代入される
string str = "First Line.¥n"
  "Second Line.¥n";

ASでは"""を使うことで複数行に渡す文字列を簡単に記述することができます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
 
 
 
 
 
// """ で始まった文字列は """で閉じる
string str = """
First Line.
Second Line.
""";

Edit

宣言文 Edit

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
// 同じ型の変数はカンマで区切ることで複数宣言することができます。
int var = 0, var2 = 10;
object@ handle, handle2;
 
// C++と同様にconstをつけることができます
const float pi = 3.141592f;
 
// 組み込み型の変数の初期化子を省略した場合,値は未初期化となり不定になります
int randaomVar;
 
// オブジェクトハンドルの場合,nullが代入されます
object@ nullHandle;
 
// ユーザー定義型の場合,デフォルトコンストラクタが呼ばれます
object defaultCtorCalled;

式文 Edit

C++同様の式文が使えます。詳しくは式の項をご覧ください。

すべてを展開すべてを収束
  1
  2
 
 
a = b; // 代入演算式
func(); // 関数呼び出し

if文 Edit

C++同等のif文が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 
-
|
!
 
 
-
|
!
 
-
|
!
if( condition ) 
{
  // condition == trueのときに実行する処理
}
 
if( value < 10 ) 
{
  // valueが10未満のときに実行する処理
}
else
{
  // valueが10以上のときに実行する処理
}

ただし,C++と異なり,C#のように条件部はbool値である必要があります。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 
 
 
-
!
 
 
 
-
!
 
// 条件部はbool値である必要があるため,次のコードはエラー
int notZeroValue = 1;
if ( notZeroValue ) // エラー:条件がbool値でない
{
}
 
// 次のように書くこと
if ( notZeroValue != 0 )
{
}

for文 Edit

C++と同等のfor文が使えます。
ただし,条件部はif文と同じようにbool値である必要があります。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 
-
|
|
|
|
|
|
-
|
!
|
-
|
!
!
 
for ( int n = 0; n < 10; ++n )
{
    // 10回する処理を書く
    // ...
    
 
    // continueやbreakも書けます
    if ( n == 5 )
    {
        continue;
    }
    if ( n == 9 )
    {
        break;
    }
}

while文 Edit

C++と同等のwhile文が使えます。
ただし,条件部はif文と同じようにbool値である必要があります。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 
 
-
|
|
|
|
-
|
!
|
-
|
!
!
int i = 0;
while( i < 10 )
{
    i++;
 
    // continueやbreakも書けます
    if ( i == 5 )
    {
        continue;
    }
    if ( i == 9 )
    {
        break;
    }
}

do-while文 Edit

C++と同等のdo-while文が使えます。
ただし,条件部はif文と同じようにbool値である必要があります。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 
 
-
|
|
|
|
-
|
!
|
-
|
!
!
int i = 0;
do
{
    i++;
 
    // continueやbreakも書けます
    if ( i == 5 )
    {
        continue;
    }
    if ( i == 9 )
    {
        break;
    }
}while( i < 10 );

switch文 Edit

C++と同様のswitch文が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 
-
|
|
|
|
|
|
|
|
|
|
|
!
  switch( value )
  {
  case 0:
    // value == 0のときにここに飛ぶ
    break;
 
  case 2:
  case constant_value:
    // value == 2 もしくは value == constant_valueのときにここに飛ぶ
    break;
 
  default:
    // 全ての条件に該当しない場合,ここに飛ぶ
  }

return文 Edit

C++と同様のreturn文が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 
-
|
!
 
-
|
!
 
float valueOfPI()
{
    return 3.141592f; // 値を返す
}
void function()
{
    return; // 値を返さずに関数の処理を終了する
}

スコープブロック文 Edit

C++と同様のスコープブロック文が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
-
|
|
|
-
|
|
|
|
!
|
|
!
 
  {
    int a; 
    float b;
 
    {
      float a; // aという同じ名前の変数を宣言したため,int aを隠してしまいます
 
      // float aの値をbに代入しています
      b = a;
    }
 
    // ここで再びint aにアクセスできるようになります
  }

Edit

代入式 Edit

C++と同様の代入式が使えます。

すべてを展開すべてを収束
  1
 
lvalue = rvalue;

代入演算式 Edit

C++と同等の代入式が使えます。
ASのシフト演算はC++のものと異なり,左シフト,符号無し右シフト,符号有り右シフトの3種類のシフトが使えます。

すべてを展開すべてを収束
  1
  2
 
 
lvalue += rvalue;
lvalue = value + rvalue;

使用可能な代入演算記号は下記の通りです。

+= -= *= /= = &= |= ^= <<= >>= >>>=

関数呼び出し Edit

C++と同様の関数呼び出しが使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
 
 
 
 
func();
func(arg);
func(arg1, arg2);
lvalue = func();

型変換式 Edit

オブジェクトハンドルの型変換の例を下記に示します。
もし,オブジェクトハンドルの型変換に失敗したらnullのオブジェクトハンドルが返されます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
 
 
 
 
 
 
 
  // オブジェクトハンドルの暗黙の変換
  // classがintfを継承しているときのみ可能
  intf @a = @clss();
 
  // オブジェクトハンドルの明示的な変換
  // 変換に失敗したらnullが返る
  clss @b = cast<clss>(a);

組み込み型の値の変換式 Edit

組み込み型の値の変換の例を下記に示します。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
 
 
 
 
 
  // float -> intの暗黙的な変換が発生
  int a = 1.0f;
 
  // 明示的な変換。aをfloatに変換している
  float b = float(a)/2;

算術演算式 Edit

C++と同様の算術演算式が使えます。

c = -(a + b);
演算記号説明左項右項結果
+正符号演算-数値数値
-負符号演算-数値数値
+加算数値数値数値
-減算数値数値数値
*乗算数値数値数値
/除算数値数値数値
%余算数値数値数値

ビット演算式 Edit

C++と同等のビット演算式が使えます。
ASではD言語のように右シフトが2種類に増えています。

c = ~(a | b);
演算記号説明左項右項結果
ビット反転-数値数値
&ビット論理積数値数値数値
ビット論理和数値数値数値
ビット排他論理和数値数値数値
<<左シフト数値数値数値
>>右シフト数値数値数値
>>>算術右シフト数値数値数値

論理演算式 Edit

C++と同等の論理演算式が使えます。
ASでは,not,and,or,xorが既存の演算記号の代わり使うことができます。

if ( a and b or not c ) {}
演算記号説明左項右項結果
not
!
論理否定-bool値bool値
and
&&
論理積bool値bool値bool値
or
||
論理和bool値bool値bool値
xor排他論理和bool値bool値bool値

等値式 Edit

C++と同様の等値式が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
 
-
!
 
-
!
if ( a == b )
{
}
if ( a != b )
{
}

比較式 Edit

C++と同様の比較式が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
 
 
 
 
if ( a < b ) {}
if ( a <= b ) {}
if ( a > b ) {}
if ( a >= b ) {}

同一性式 Edit

2つのオブジェクトハンドルが示すものが同じかどうかを調べる式です。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 
 
-
|
!
 
-
|
!
 
-
|
!
object@ a,b;
if ( a is null )
{
    // aがnullのときに実行される処理
}
if ( a !is null )
{
    // aがnullでないときに実行される処理
}
if ( a is b )
{
    // aとbが同じオブジェクトを指している,もしくは両方ともnull
}

インクリメンタル式・デクリメンタル式 Edit

C++と同様のインクリメンタル式,デクリメンタル式が使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 
 
 
 
 
 
 
 
 
 
 
// a = i; i += 1; と同じ意味
a = i++;
 
// i += 1; b = i; と同じ意味
b = ++i;
 
// c = i; c -=1; と同じ意味
c = i--;
 
// i -= 1; d = i; と同じ意味
d = --i;

インデクス式 Edit

C++と同様のインデクス式が使えます。
添え字に使う型は,インデクス式がオーバーロードできるためオブジェクトのタイプごとに異なります。

arr[i] = 1;

条件式 Edit

C++と同等の三項条件式が使えます。
if文と同様に,条件部はbool値である必要があります。

condition ? a : b;

メンバアクセス Edit

object.property = 1;
object.method();

C++と同様にオブジェクトのメンバにアクセスできます。

ASではオブジェクトにプロパティアクセサを持つことができるため
メンバ変数にアクセスしているように見えて,実際は関数を呼び出しているということもありえます。
詳細はクラスのプロパティアクセサの項をご覧ください。

オブジェクトハンドルアクセス Edit

オブジェクトのハンドルにアクセスする際に頭に@をつけます。
この記号を使うことで,オブジェクトハンドルが指すオブジェクトを変更したり,参照したりします。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
 
 
 
 
 
  // objectが指すオブジェクトの参照をhandleにコピー
  @handle = @object;
 
  // handleが指すオブジェクトをnullに設定
  @handle = null;

丸括弧 Edit

C++と同様の丸括弧が使えます。

a = c * ( a + b );

スコープ解決 Edit

C++に似たスコープ解決演算子が使えます。
::を使うことでグローバル変数・関数を指定することができます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
 
 
-
|
|
!
  int value;
  void function()
  {
    int value;        // グローバル変数のvalueを隠してしまう
    ::value = value; // グローバル変数のvalueにローカル変数のvalueを代入している
  }

オブジェクトハンドル Edit

オブジェクトハンドルはオブジェクトの参照を保持することができる型です。
オブジェクトハンドルを使うことで,1つのオブジェクトを複数の変数からアクセスできるようになります。
C++でいうポインタや参照と同じようなものだと考えてください。

オブジェクトハンドル変数の宣言 Edit

オブジェクトハンドルの型は型名 + @で表現します。

object@ obj_h;

このコードでは,obj_hにnull参照が保持されます。
null参照が保持されている状態は,オブジェクトの参照を保持していない状態と考えてください。

メンバへのアクセス Edit

オブジェクトハンドルが参照しているオブジェクトのメンバへのアクセスは
通常のオブジェクトのメンバへのアクセスと同じようにアクセスします。

object obj;
object@ obj_h;
obj.Method();
obj_h.Method();

もし,オブジェクトハンドルがnull参照を保持している状態でメンバへアクセスしようとすると
例外が発生し,実行中のスクリプトが停止します。

値のコピー Edit

オブジェクトハンドルの変数に対して代入演算子=を使うと,
通常のオブジェクト変数に対して代入演算を記述したときと同じことが行われます。

object obj;
object@ obj_h;
obj_h = obj;

もちろん,オブジェクトハンドルがnull参照を保持している場合は例外が発生します。

参照のコピー Edit

オブジェクトハンドルが保持する参照をコピーしたい場合は@記号を使います。

object obj;
object@ obj_h;
@obj_h = @obj;

同一性チェック Edit

同一性式を使うことで,2つのオブジェクトハンドルが同じオブジェクト参照を保持しているか調べることが出来ます。

object@ obj_a, obj_b;
if ( obj_a is obj_b ) {}
if ( obj_a !is null ) {}

オブジェクトの寿命 Edit

オブジェクトハンドルが参照するオブジェクトは
全てのオブジェクトハンドルから参照を保持されなくなった時点で解放されます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 
-
|
|
|
|
|
!
 
 
 
 
 
 
 
  object@ obj_h;
  {
    object obj;
    @obj_h = @obj;
 
    // 通常は,スコープブロックの終了時にオブジェクトは解放されます
    // しかし,オブジェクトハンドルが参照を保持しているため,ここでは解放されません
  }
 
  // obj_hはオブジェクトの参照を保持しているため,メンバにアクセスすることができます
  obj_h.Method();
 
  // このように,明示的にオブジェクトハンドルの参照を解除するか
  // スコープを抜けるタイミングでオブジェクトは解放されます
  @obj_h = null;

ポリモフィズム Edit

オブジェクトハンドルを使うことで基底クラス・インターフェースのへの変換やダウンキャストを実現します。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 
 
 
 
 
 
 
 
-
|
|
|
-
|
!
|
-
|
!
!
 
  interface I {}
  class A : I {}
  class B : I {}
 
  // インターフェースとして,オブジェクトハンドルに参照を保持させる
  I @i1 = A();  
  I @i2 = B();
 
  void function(I @i)
  { 
    // ダウンキャストをする場合,cast演算を使って変換を試みます
    A @a = cast<A>(i);
    if( a is null )
    {
      // ダウンキャストに失敗すればnull参照が格納されます
    }
    else
    { 
      // ダウンキャストに成功すれば有効な参照が格納されます
    }
  }

関数 Edit

変数 Edit

インターフェース Edit

ASのインターフェースはC#やD言語と同等のものと考えてもらって構いません。
インターフェースにはC++でいう純粋仮想関数を宣言することができます。
ただし,C#やD言語のインターフェースとは異なり,インターフェースが他のインターフェースを継承することはできません。
その代わり,クラスは複数のインターフェースを継承することができます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 
-
|
!
 
 
 
-
|
-
!
!
 
 
 
 
 
 
  // インターフェースの宣言
  interface MyInterface
  {
    void DoSomething();
  }
 
  // MyInterfaceを実装するクラスの宣言
  class MyClass : MyInterface
  {
    void DoSomething()
    {
    }
  }
 
  // 複数のインターフェースの継承例
  interface IntfA {} 
  interface IntfB {}
  class Example : IntfA , IntfB {}

import Edit

列挙型 Edit

C++と同様のenumが使えます。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
 
-
|
|
|
|
!
  enum MyEnum
  {
    eValue0,
    eValue2 = 2,
    eValue3,
    eValue200 = eValue2 * 100
  }

typedef Edit

他の型のエイリアスを宣言することができます。
現在のバージョンでは組み込み型に限定されているようです。

typedef float real32;
typedef double real64;

クラス Edit

ASのクラスはC++に似ていますが,仕様が異なる箇所がいくつかあるので注意してください。

すべてを展開すべてを収束
  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
 
 
-
|
|
-
|
!
|
|
|
-
!
|
|
|
-
|
!
|
|
|
-
|
!
|
|
|
!
  // クラスの宣言
  class MyClass
  {
    // デフォルトコンストラクタ
    MyClass()
    {
      a = 0;
    }
 
    // デストラクタ
    ~MyClass()
    {
    }
 
    // 引数指定付きコンストラクタ
    MyClass(int a)
    {
      this.a = a;
    }
 
    // メンバ関数
    void DoSomething()
    {
      a *= 2;
    }
 
    // メンバ変数
    int a;
  }

アクセス修飾子 Edit

ASのクラスはC++のようにアクセス修飾子(public,protected,private)が存在しません。
複数人でコーディングするときは,どのメンバが外部からアクセスしてよいメンバなのか分からなくなりますので
命名規則などを作り運用でカバーしましょう。

コンストラクタとデストラクタ Edit

C++のように,コンストラクタ・デストラクタが定義できます。
デフォルトコンストラクタ,デフォルトデストラクタは定義しなければ自動生成されます。

ただ,自動で生成されるデフォルトコンストラクタは組み込み型のメンバ変数を初期化しません。
それらのメンバ変数は未初期化になるため気を付けましょう。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
-
|
|
|
-
|
|
!
!
 
 
-
|
|
!
 
 
 
 
 
class Vector2
{
    float x;
    float y;
    Vector2()
    {
        x = 0;
        y = 0;
    }
};
 
class Obj
{
    int a;
    Vector2 vec;
};
 
Obj obj; 
// obj.aは未初期化になる
// obj.vecはVector2のデフォルトコンストラクタが実行されるためちゃんと初期化される

また,ASはC++と異なりデフォルトコンストラクタは必ず生成されるので注意しましょう。
(C++ではコンストラクタを定義するとデフォルトコンストラクタは自動生成されません)

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 
-
|
|
|
-
|
|
!
!
 
 
class Vector2
{
    float x;
    float y;
    Vector2(float aX, float aY)
    {
        x = aX;
        y = aY;
    }
};
 
Vector2 vec; // 自動生成されたデフォルトコンストラクタが実行されてしまう。そのためvec.x,vec.yは未初期化になる。

クラスの継承・インターフェースの実装 Edit

ASのクラスはC#・D言語のように1つだけクラスを継承することができ,
インターフェースは複数実装(継承)することができます。

ASのクラスのメンバ関数は,JAVAやD言語ように全て仮想関数として宣言されます。
そのためどのメンバ関数もオーバーライドすることができます。

すべてを展開すべてを収束
  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
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 
-
|
!
 
-
|
!
 
 
 
-
|
|
|
-
|
!
|
-
|
!
|
|
|
!
 
 
 
-
|
-
|
!
|
-
|
!
|
|
-
|
!
!
 
interface IUpdatable
{
    void update();
};
interface IDrawable
{
    void draw()const;
};
 
// 2つのインターフェースを実装する
class Chara : IUpdatable , IDrawable
{
    int hitPoint;
 
    Chara()
    {
        hitPoint = 0;
    }
    Chara(int aHitPoint)
    {
        hitPoint = aHitPoint;
    }
 
    void update() {}
    void draw()const {}
};
 
// 1つのクラスを継承する
class Enemy : Chara
{
    Enemy()
    {
        // Chara()が自動で呼ばれる
    }
    Enemy(int aHitPoint)
    {
        super( aHitPoint ); // 継承元のコンストラクタはこのように呼び出すことができる
    }
 
    void update()
    {
        Chara::update(); // 隠蔽した関数はこのように呼び出すことが出来る
    }
};

ちなみに,ASのsuperを使ったコンストラクタの呼び出し位置の制約はないようです。
(C#やD言語では先頭でしかできない仕様)

演算子オーバーロード Edit

ASはC++のように演算子をオーバーロードすることができます。
演算記号に該当する関数名を実装することで演算子オーバーロードを実現できます。

単項演算子
記号関数名
-opNeg
opCom

これらの演算子を定義していてコード中で演算子が使われると,コンパイル時に a.opfunc() という形に展開されます。

等値演算子
記号関数名
==opEquals
!=opEquals

a == ba.opEquals(b)b.opEquals(a)のどちらかに展開されます。
opEqualsはbool値を返す関数として定義する必要があります。

比較演算子
記号関数名
<opCmp
<=opCmp
opCmp
>=opCmp

比較演算は a.opCmp(b) か b.opCmp(a)のどちらかに展開されます。
opCmp関数はint値を返す関数として定義する必要があります。
a.opCmp(b)のとき,a < bなら-1を,a==bなら0を,a > bなら1を返すようにしてください。

opCmpが定義されていればopEqualsは定義されていなくてもopCmpを使うことで等値演算を実装できます。
しかしながら,等値演算は比較演算と比べて処理が軽いケースが多いです。
処理負荷の最適化を考えるならば,等値演算もオーバーロードしたほうがいいでしょう。

代入演算子
記号関数名
=opAssign
+=opAddAssign
-=opSubAssign
*~opMulAssign
/=opDivAssign
%=opModAssign
&=opAndAssign
|=opOrAssign
^=opXorAssign
<<=opShlAssign
>>=opShrAssign
>>>=opUShrAssign

代入演算子が使用されるとa.opfunc(b)というコードに展開されます。
代入演算子の関数は次のように実装してください。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
 
-
|
|
|
|
!
obj@ opAssign(const obj&in other)
{
    // 代入処理
 
    // 自分自身のオブジェクトハンドルを返すようにしてください
    return this;
}

スクリプト上で宣言されたクラスは自動でコピー演算子(opAssign)が実装されます。
自動で生成される挙動とは異なる挙動を実装したいときにopAssignをオーバーロードしてください。

算術演算子
記号関数名関数名(反転)
+opAddopAdd_r
-opSubopSub_r
*opMulopMul_r
/opDivopDiv_r
%opModopMod_r
&opAndopAnd_r
opOropOr_r
opXoropXor_r
<<opShlopShl_r
>>opShropShr_r
>>>opUShropUShr_r

『a 演算記号 b』と記述されると a.opfunc(b) か b.opfunc_r(a) に展開されます。

プロパティアクセサ Edit

ASではC#やD言語のようにプロパティアクセサを実装することができます。
クラスのメンバとして実装することはもちろん,グローバル変数としても実装することができます。

すべてを展開すべてを収束
  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
 32
 33
 34
 35
 36
 37
 
 
-
|
-
|
|
!
|
|
-
|
|
|
|
|
|
!
|
|
|
!
 
 
 
-
|
|
|
|
|
|
|
|
|
!
 
  // プロパティアクセサを使うクラスの宣言
  class MyObj
  {
    int get_prop() const
    {
      // propの値を返す
      return realProp;
    }
 
    void set_prop(int val)
    {
      // propの値を設定
      // 値のクリッピングをしてから代入する
      if( val > 1000 ) val = 1000;
      if( val < 0 ) val = 0;
 
      realProp = val;
    }
 
    // propがアクセスする変数
    int realProp;
  }
 
  // プロパティアクセサの動作例
  void Func()
  {
    MyObj obj;
 
    // プロパティアクセサで実装されたプロパティはメンバ変数のようにアクセスします
    // set_prop(10000)が呼ばれます
    obj.prop = 10000;
 
    // get_propがよばれます
    // クリッピング処理が呼ばれているはずなので,値は1000が返るはずです
    assert( obj.prop == 1000 );
  }

    ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS