JavaプログラマーからみたVala(7) その他
原典は、“Vala for Java Programmers”(2011年3月13日取得)です。
- JavaプログラマーからみたVala (1) ソースコード
- JavaプログラマーからみたVala(2) 型
- JavaプログラマーからみたVala (3) クラス
- JavaプログラマーからみたVala (4) クラス②
- JavaプログラマーからみたVala(5) 通知
- JavaプログラマーからみたVala(6) 引数
- JavaプログラマーからみたVala(7) その他
- WindowsでValaを動かす
******************************
構造体
構造体(struct)は、Javaには存在しない概念です。構造体とクラスのちがいを理解してもらうために、Point型の2つの実装をご覧に入れます。実装の一つはクラスとして、もう一つは構造体としてなされています。
class Point { public x; public y; public Point (int x, int y) { this.x = x; this.y = y; } public void print () { stdout.printf ("(%d, %d)", this.x, this.y); } } struct Point { public x; public y; public Point (int x, int y) { this.x = x; this.y = y; } public void print () { stdout.printf ("(%d, %d)", this.x, this.y); } }
ご覧のとおり、上記の2つの実装において、ちがうのはただstruct/classというキーワードのみです。にもかかわらず構造体はプログラムの動作においてクラスと異なっています。
// Class var p1 = new Point (2, 4); // p1がヒープに配置される var p2 = p1; // 参照の代入 p2.x = 3; p1.print (); // => (3, 4) p1の状態が変化している p2.print (); // => (3, 4) var p3 = new Point (3, 4); p2 == p3; // => 結果はfalse。(格納された値は同じでも参照が異なる) // Struct var p1 = Point (2, 4); // p1はスタックに配置される var p2 = p1; // p1のコピーがp2に代入される p2.x = 3; p1.print (); // => (2, 4) p1は変化しない p2.print (); // => (3, 4) var p3 = Point (3, 4); p2 == p3; // => 結果はtrue。 (同じ値だから)
構造体はヒープに配置されません。(まさしくそれが、構造体の生成にnew演算子が使用されない理由です。)何よりも重要なちがいは、変数に代入される際にコピーされる点です。構造体は値型であり、参照型ではないのです。基本的にintやdoubleなどと同様に振る舞うということです。
構造体は継承やシグナル、インターフェースの実装をサポートしていません。
同期化
Javaの場合: synchronized修飾子があります。
Valaの場合: lockの仕組みは、メソッドに対して適用することができません。適用できるのはメンバーオブジェクトに対してだけです。*1
条件的コンパイル
Javaの場合: 条件的コンパイルの仕組みは存在しません。*2
Valaの場合: #if、#elif、#else、#endifを使用したシンプルな条件指定が可能です。しかしながらC言語のプリプロセッサーのような、マクロプリプロセッサー(macro preprocessor)とは異なります。
条件的コンパイルのサンプル(Conditional Compilation Example)を参照してください。
メモリー管理
Javaの場合: ガーベージコレクションの仕組みがあります。
Valaの場合:自動参照カウントの仕組みがあります。
これにはメリットとデメリット(advantages and disadvantages)があります。参照カウント方式は決定論的ですが、いくつかのケースで循環参照におちいる危険があります。このような場合に循環を断ち切る方策として、開発者は弱参照(weak references)を使用できます。Valaでは弱参照のためにweakキーワードが用意されています。
「説明されているValaのメモリー管理」(Vala's Memory Management Explained)を参照してください。
staticな初期化処理
Javaの場合: staticな初期化ブロックがあります。このブロックはインスタンスが生成されるか、staticなメンバーが参照されたときに呼び出されます。
public class Foo { static { System.out.println("Static initializer block invoked."); } }
Valaの場合: static construct { } ブロックがあります。クラスもしくはそのクラスの直接/間接のサブクラスがインスタンス化されるとき、このブロックも呼び出されます。このブロックは、プログラム内でクラスが使用される際に、かならず1回だけ呼び出されることが保証されています。
class Foo : Object { static construct { stdout.printf ("Static constructor invoked.\n"); } }
加えてVala言語のクラスはconstruct { } ブロックを持つことができます。このブロックはクラスが最初に使用される際に1回実行されます。またこのクラスのサブクラスが最初に使用される際にも1回実行されます。
可変長引数(Varargs)
Javaの場合:
String format(String pattern, Object... arguments) { // ... }
Valaの場合: C言語スタイルの可変長配列が使用できます。タイプセーフではありません。
string format (string pattern, ...) { var l = va_list (); // ... }
より多くの情報が、「Valaチュートリアル」で見られます。タイプセーフな可変長配列は、paramsキーワードとともに計画されています。
ネイティブコール
Javaの場合: nativeキーワードとJNIの仕組みを使用します。
Valaの場合: すべてのメソッドは“native”コールです。C言語の関数をバインディングするには、手っ取り早くするならexternキーワードを、そうでなければ.vapiファイルを使用します。呼び出したいC言語で書かれた関数の名前を指定するにはCCode属性を使用します(Vala言語で記述するメソッド名とちがう場合だけです)。
public class MainClass : Object { [CCode (cname = "SampleMethod")] public static extern int sample_method (int x); static void main () { stdout.printf ("sample_method () returns %d\n", sample_method (5)); } }
コンパイラには、-X –l...オプションとともにライブラリの名前を渡します。(-Xオプションはこのオプションの次のオプションがCコンパイラに渡されるものであることをあらわします。)
$ valac demo.vala -X -lfoo
外部メソッド(関数)が定義されたC言語のソースファイルをValaコンパイラに対して渡すこともできます。これによりVala言語とC言語のソースコード・プロジェクトを混合させることができます。
$ valac demo.vala foo.c
Valaではできないこと
-
- finalクラスは存在しません。(sealedクラスが計画されています。)staticクラスは存在しません。(代わりにネストされたネームスペースを使用します。)
- 匿名内部クラスは存在しません。(代わりにデリゲートとクロージャを使用します。)
- ジェネリック型の引数に対する制約はありません。*3
- オブジェクトの文字列変換に関する暗黙の規約は存在しません。(toString()メソッドが一般的なかたちで存在しないため。)とはいえ、to_string()メソッドを持つ型は、文字列テンプレート(@”...”)によりサポートされています。*4
- 名前付きbreakとラベルの機能はありません。
- strictfpやtransient修飾子は存在しません。
このチュートリアルがカバーできていない言語の特徴
- 非同期メソッド
- 代替的なコンストラクション形態(Alternative construction scheme。GObjectスタイルのそれ)
これらについてより多くの情報を得るには、「Vala言語の一般的なチュートリアル」(general Vala tutorial)を参照してください。
******************************
※原典ではまだいくつかの節が続いていますが、いかにも書き足したという印象なのと、内容がそれほど一般的なものであるように思われないのでここに翻訳は載せません。
*1:訳者:ValaにはJavaにおけるsynchronizedブロックに対応するlockブロックが存在します。しかしこのブロックによりロックを取得できるのは、そのメソッドの所属するクラスのメンバーオブジェクト──intなども含む──についてのみです。[http://live.gnome.org/Vala/Tutorial:title=チュートリアル]のほうに例が載っています。
*2:訳者:そもそも中間コードこそが基本的な配布の単位なので。
*3:訳者:型名の<>で囲われている部分のことでしょうか?
*4:訳者:つまり文字列テンプレートでも使用可能なようなVala言語的に妥当なクラスはto_string()メソッドを実装しているべきである、ということです。