原典は、“Vala for Java Programmers”(2011年3月13日取得)です。
******************************
JavaプログラマーからみたVala (3) クラス
継承
Javaの場合: extendsとimplementsを使用します。
public class Demo extends Foo implements Bar {
public Demo() {
super();
}
}
Valaの場合: コロンとそれに続くカンマ区切りリストであらわします。このリストには親クラスもインターフェースもともに含まれます。
public class Demo : Foo, Bar {
public Demo () {
base ();
}
}
Vala言語では親クラス(super)を基本クラス(base)と呼びます。
オブジェクトベースクラス
Javaの場合: すべてのクラスはObject(java.lang.Object)から暗黙的に継承します。
public class Foo {
// ...
}
Valaの場合: Object(Glib.Object)からの暗黙的な継承は行われません。
public class Foo : Object {
// ...
}
Glib.Objectからの継承を行わないとどうなるのでしょうか? このような場合、そのクラスは若干軽量になる一方、プロパティ変更通知(property change notifications)などのいくつかの機能を欠いたものになります。そしてこのクラスは共通基本クラスを持たないことになります。たいていの場合、Glib.Objectからの継承は必要となるでしょう。
メソッド多重定義
Javaの場合: 以下の例のようにメソッドの多重定義(overloading)が行えます。
public class Demo {
public void draw(String text) { }
public void draw(Shape shape) { }
/* メソッドのオーバーロード、
そしてより引数の数の少ないメソッドによる、
引数の数の多いそれの利用*/
void f(int x, String s, double z) { }
void f(int x, String s) {
f(x, s, 0.5);
}
void f(int x) {
f(x, "hello");
}
}
Valaの場合: メソッドの多重定義はできません。別名を付けるか、引数にデフォルト値を指定することで代わりとします。
public class Demo : Object {
public void draw_text (string text) {
}
public void draw_shape (Shape shape) {
}
/* 引数にデフォルト値が指定されたメソッド */
void f (int x, string s = "hello", double z = 0.5) {
}
}
Vala言語がメソッド多重定義の機能をサポートしないのは、Valaのライブラリが、C言語コードからアクセス可能であるよう意図して記述されているからです(意訳)。
コンストラクタ多重定義
Javaの場合: コンストラクタの多重定義ができます。
public class Foo {
public Foo() { }
public Foo(int foo) { }
public Foo(String bar) { }
}
new Foo();
new Foo(42);
new Foo("hello");
Valaの場合: 多重定義ではなく、名前付きコンストラクタ(named constructors)を使用します。
public class Foo : Object {
public Foo () { }
public Foo.with_foo (int foo) { }
public Foo.from_bar (string bar) { }
}
new Foo ();
new Foo.with_foo (42);
new Foo.from_bar ("hello");
コンストラクタ連鎖
Javaの場合: “this()”記法で実現します。
class Foo {
public Foo() {
this("bar");
}
public Foo(string bar) {
}
}
Valaの場合: “this()”記法もしくは“this.コンストラクタ名 ()”記法で実現します。
class Foo : Object {
public Foo () {
this.with_bar ("bar");
}
public Foo.with_bar (string bar) {
}
}
オーバーライド
Javaの場合: すべてのメソッドはデフォルトで仮想メソッド(C#で導入された概念。オーバーライド可能なメソッド)です。オーバーライドを阻止するにはfinal修飾子を使用します。
public class Super {
public int myMethod(int x, int y) { }
public final void anotherMethod() { }
}
public class Sub extends Super {
@Override
public int myMethod(int x, int y) {
super.myMethod(x, y);
// ...
}
}
Valaの場合: すべてのメソッドは、デフォルトで非仮想メソッド(オーバーライド不可能なメソッド)です。オーバーライドを可能にするには明示的にvirtual修飾子を使用する必要があります。 他方、Vala言語には@Overrideアノテーションの代わりにoverride修飾子があり、この修飾子の使用は任意ではありません(強制です)。
public class Super : Object {
public virtual int my_method (int x, int y) { }
public void another_method () { }
}
public class Sub : Super {
public override int my_method (int x, int y) {
base.my_method (x, y);
// ...
}
}
アクセス修飾子
Java | Vala |
public | public |
protected | protected |
package-private (デフォルト) | internal |
private | private (デフォルト) |
クラスメンバーのアクセスはデフォルトでprivateですが、publicアクセスのメンバーと対称的にさせるために、明示的にprivate修飾子を使用することもできます。
インターフェース
Javaの場合: インターフェースのメソッドは暗黙のうちに抽象メソッドです。
public interface Foo {
public void foo(int i);
public int bar(String s, double d);
}
Valaの場合: abstract修飾子は明示的に使用する必要があります。
public interface Foo {
public abstract void foo (int i);
public abstract int bar (string s, double d);
}
なぜでしょう? それはVala言語におけるインターフェースが非抽象メソッド(実装をともなうメソッド)をメンバーとすることができるからです。つまりVala言語のインターフェースは、いわゆるミックスイン(mixins。限定的な多重継承)を実現するために利用できるのです。
Vala言語におけるインターフェースは、──例えばファクトリーメソッドのような──staticメソッドを持つこともできます。
Javaの場合: インターフェースは継承可能です。
public interface IfaceA {
public void methodA();
}
public interface IfaceB extends IfaceA {
public void methodB();
}
public class Demo implements IfaceB {
public void methodA() { }
public void methodB() { }
}
Valaの場合: インターフェースは必要条件として働きます。
interface IfaceA : Object {
public abstract void method_a ();
}
interface IfaceB : Object, IfaceA {
public abstract void method_b ();
}
class Demo : Object, IfaceA, IfaceB {
public void method_a () { }
public void method_b () { }
}
Valaでは、インターフェースは他のインターフェースから継承できません。しかし他のインターフェースを必要条件として宣言できます。これによりおおよそ同じことを実現できます。インターフェースは、インターフェースだけでなくクラスも前提条件として宣言することができます。これにより、あるインターフェース(を継承したあるクラス)のインスタンスが、Glib.Objectのサブクラスでもあることを保証することができます。この事実──インターフェースは他のインターフェースのメンバーを継承できない──は、ほとんど技術的なちがいでしかありません。実際のところVala言語のインターフェースのシステムは、Javaにおけるそれと同じように働きます。ただ、Valaにおいてはクラス継承を必要条件とするという機能もある、ということです。
******************************
JavaプログラマーからみたVala (4)につづく──
0 件のコメント:
コメントを投稿