M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

JavaプログラマーからみたVala(6) 引数

原典は、“Vala for Java Programmers”(2011年3月13日取得)です。

******************************

引数の向き

Vala言語ではメソッドはout引数もしくはref引数を持つことができます。もしあるメソッドの引数が、メソッドのシグネチャの中でoutもしくはrefとマークされている場合、それはこのメソッドが外部から渡された変数の値を書き換えることができるということを意味します(out引数もしくはref引数しか渡せません)。そしてその変更はメソッドの処理が完了した後も有効なのです。もし渡された変数が参照型の場合、メソッドはその参照自体を書き換えられるのです(変数が参照するオブジェクトの状態を変更するというのではありません。変数が参照するオブジェクトを別のオブジェクトにすることができるのです)。

outとrefのちがいは、refの場合メソッドに渡される引数は事前に初期化済みでないといけないのに対して、outではその必要はなく、メソッド内部で初期化が実施されるということです。

これらのキーワードは、メソッドの定義コードと、メソッド呼び出しコードの双方で指定する必要があります。

/*
 * This method takes a normal argument, an 'out' argument
 * and a 'ref' argument.
 */
void my_method (int a, out int b, ref int c) {
    a = 20;  // メソッド呼び出し元には効果は及ばない。

    // 引数bは初期化されていない可能性がある。
    b = 30;  // 引数bが初期化される。呼び出し元の変数に反映される。
    c = 40;  // 呼び出し元の変数に反映される。
}

void main () {
    int x = 2
    int y;      // 初期化されないまま。
    int z = 4;  // refキーワード付きでメソッドに渡す前に初期化が必要。
    my_method (x, out y, ref z);
    stdout.printf ("%d %d %d\n", x, y, z);  // => "2 30 40"
    // xは変更されないが、yとzは変更されている。
}

Null可能性(Nullability)

Vala言語ではメソッドの参照型引数について、それがnullでもよい場合には、クエスチョンマーク(?)を型名の後に付ける必要があります。

void my_method (Object? a, Object b) { }

void main () {
    my_method (null, new Object());  // コンパイルできる(第1引数はnullでもよい)
    my_method (null, null);          //コンパイルできない(第2引数はnullではいけない)
}

null可能性は実行時にも(部分的には)コンパイル時にもチェックされます。このチェックはnull参照エラーを阻止する助けになります。
--enable-experimental-non-nullオプションにより、厳格なnull可能性チェック(実験的機能)を有効化することもできます。この場合、Valaはコンパイル時に、メソッド引数のみならず、すべての参照型変数をチェックします。例えば次のコードは、厳格なnull可能性チェックの下ではコンパイルできないでしょう。

void main () {
    string? a = "hello";
    string b = a; // Error: 'a' はnullでもよいが、'b'はnullであってはいけない
}

どうしてもnull可能な変数をnull不可能変数に代入したい場合(!)を使用するとコンパイルできます。

void main () {
    string? a = "hello";
    string b = (!) a;
}

これはJACKやJastAddなどのJavaにおける試み(@NonNullアノテーションを用いる)と同様の実験です。

引数チェック

Java の場合:*1

void method(double d, int i, Foo foo) {
    if (d < 0 || d > 1.0)
        throw new IllegalArgumentException();
    if (i < 0 || i > 10)
        throw new IllegalArgumentException();
    if (foo == null)
        throw new IllegalArgumentException();
    // ...
}

Valaの場合: 参照型引数の場合、クエスチョンマークによりnull可能であることを印付けない限り、暗黙的なnullチェックが実施されます。開発者がこれをチェックするためのコードを記述する必要はありません。メソッドはその他の事前条件を持つこともできます。

void method (double d, int i, Foo foo)
     requires (d >= 0.0 && d <= 1.0)
     requires (i >= 0 && i <= 10)
{
    // ...
}

Vala言語では、事後条件(返却値についての条件)も指定することができます。例えば──

int square (int i)
    ensures (result >= 0)
{
    return i * i;
}

ここでresultは返却値をあらわす特別な変数です。
例外(エラー)は回復可能なエラー(データベースエラー、IOエラーなど)に対して使用します。事前条件やアサーションassert(...))は不正な引数などプログラミングエラーに対して使用します。

******************************

JavaプログラマーからみたVala (7)につづく──

*1:訳者:ようするにJavaにおいて、メソッド引数に対する言語組み込みの検証システムは、型チェックだけです。