ラベル java の投稿を表示しています。 すべての投稿を表示
ラベル java の投稿を表示しています。 すべての投稿を表示

2011年3月13日日曜日

JavaプログラマーからみたVala (4) クラス②

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

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

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

JavaプログラマーからみたVala (4) クラス②

列挙型

Javaの場合: 列挙型はクラスをベースにしています。

Valaの場合: 列挙型は整数をベースにしています。メソッドは持てますが、コンストラクターやフィールドなどは持つことができません。
enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

    public bool is_hot () {
        return this == SUMMER;
    }
}

実行時の型判別

動的型チェック

Javaの場合: instanceof演算子を使用します。
Valaの場合: is演算子を使用します。

動的型キャスト

Javaの場合: Foo foo = (obj instanceof Foo) ? (Foo) obj : null

Valaの場合: Foo foo = obj as Foo

もちろん、 "(obj is Foo) ? (Foo) obj : null"も同様に有効な式です。

型情報を取得する

Javaの場合:
Class c = Foo.class;
System.out.println(c.getName());
Foo = (Foo) c.newInstance();

Valaの場合: typeof()を使用します。
Type t = typeof (Foo);
stdout.printf ("%s\n", t.name ());
Foo o = (Foo) Object.new (t);

オブジェクトの破棄

Javaの場合: 終了化子(finalizers)は、非決定論的です。
public class Foo {
    @Override
    protected void finalize() {
    }
}

Valaの場合: デストラクタ(destructors)は、決定的です。
public class Foo : Object {
    ~Foo () {
    }
}

アノテーション

Javaの場合: アノテーションは自己定義的です。

Valaの場合: アノテーションの代わりに属性(attributes)を用います。属性はコンパイラに組み込まれています。書式は、“[AttributeName (param1 = value, param2 = value)]”というかたちです。バインディング(bindings)やD-Busインターフェースのためにしばしば使用さてます。バインディングのために使用されるいちばんよく見る属性は、“[CCode (...)]”です。

プロパティ

Javaの場合: Bean規約が用いられます。getX()setX()という形式のメソッドです。
public class Person {
    private int age = 32;

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        Person p = new Person();
        p.setAge(p.getAge() + 1);
    }
}

Valaの場合: プロパティ──get {} ・ set {}ブロック──がサポートされており、フィールドのようにアクセスできます。
public class Person : Object {
    private int _age = 32;

    public int age {
        get { return _age; }
        set { _age = value; }
    }
}

void main () {
    var p = new Person ();
    p.age++;
}

標準的な実装であれば、さらに短くできます。
public class Person : Object {
    public int age { get; set; default = 32 }
}

デリゲート、クロージャ

Javaの場合: デリゲート・パターンの実装は、匿名内部クラスを使用することになります。
public interface MyDelegateType {
    public void invoke(int a, double b);
}

public class Demo {
    private static void foo(MyDelegateType deleg) {
        deleg.invoke(32, 0.25);
    }

    public static void main(String[] args) {
        MyDelegateType deleg = new MyDelegateType () {
            public void invoke(int a, double b) {
                System.out.println("a = " + a + "; b = " + b);
            }
        };
        deleg.invoke(42, 0.75);
        foo(deleg);
    }
}

Valaの場合: Vala言語は、デリゲートとクロージャをサポートしています。
delegate void MyDelegateType (int a, double b);

void foo (MyDelegateType deleg) {
    deleg (32, 0.25);     // invoke delegate
}

void main () {
    MyDelegateType deleg = (a, b) => {
        stdout.printf ("a = %d; b = %g\n", a, b);
    };
    deleg (42, 0.75);     // invoke delegate
    foo (deleg);          // pass delegate to a method
}

クロージャは外部スコープ(それ自身が定義されたスコープ)のローカル変数を束縛する無名のメソッドです(訳者:JavaScriptの関数がまさにそれです。Java6ではfinal宣言された変数でないと外部スコープの変数にはアクセスできませんが、JavaScriptも含め他の言語の中にはこうした変数の読み書きを行えるものがあります。JavaScriptではこの方法で他のコードがアクセスできない文字通り匿名の名前空間を展開・保持するテクニックが頻繁に使用されます)。クロージャはデリゲート型の変数に代入したり、デリゲート型の引数として他のメソッドに渡すことができます。

Java言語においては、匿名内部クラスにより、クロージャのまねごとができます。しかし匿名内部クラスが束縛できる外部スコープ・ローカル変数は、final宣言されたものだけです。一方、Vala言語ではクロージャはいかなる変数でも束縛できます。Java7ではクロージャのサポートが計画されています。メソッドは直接デリゲート変数に代入できます。
delegate int MyDelegateType (int a, double b);

int add (int a, int b) {
    return a + b;
}

int sub (int a, int b) {
    return a - b;
}

void main () {
    MyDelegateType deleg = add;
    int sum = deleg (2, 3);
    deleg = sub;
    int diff = deleg (8, 4);
}

このことが示すのは、メソッドは(訳者:クロージャに限らずこれまで登場してきたあらゆる種類のメソッドは)オブジェクト同様に変数に格納したり引数として渡したりできるということです。

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

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

JavaプログラマーからみたVala (3) クラス

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

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

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

JavaプログラマーからみたVala (3) クラス

継承

Javaの場合: extendsimplementsを使用します。
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)につづく── 

JavaプログラマーからみたVala (2) 型

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

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

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

JavaプログラマーからみたVava(2)

基本型
  • 標準的な型(intやlongなど)のサイズはアーキテクチャに依存します。こうした型のサイズを求めるには、sizeof()を使用します。例えば、sizeof(int)といった具合です。
  • Valaで追加された型──int8、int16、int32、int64(すべて符号あり)、uint8、uint16、uint32、uint64(すべて符号なし)は、アーキテクチャ非依存であることが保証されています。
  • byte型はありません。(代わりにuint8を使用しましょう。)
  • Javaにおけるboolean型は、Valaではbool型です。 
  • Valaで追加された基本型には、unichar型があります。これはユニコード文字をあらわします。
定数修飾子は、finalではなくconstです。

Vala言語では基本型もメソッドを持ちます。例えば以下のように──
int a = -4.abs ();
string s = a.to_string ();
int b = int.max (5, 7); // int型の静的メソッドが呼ばれています。


文字列型

Javaの場合:

型名は、Stringです。
意味的等価性をチェックするにはequals(String)メソッドを使用します。

Valaの場合:

型名はstringです。(小文字です。)
意味的等価性をチェックするには==演算子を使用します。

Valaでは文字列の(==演算子による)比較は、内容ベースで行われます。参照ベースではありません。<、>、<=、>=などの比較演算子は、文字列の辞書的比較に使用できます。文字列はswitch文で使用できます。

Vala文字列はUTF-8で保持されます。

Vala言語における文字列のその他の特徴

Vala言語は逐語的文字列リテラル(verbatim strings)をサポートしています。逐語的文字列リテラルは、3連ダブルクオテーションで囲います("""...""")。
string verbatim = """Verbatim strings don't evaluate escape sequences
like \n, \t, ... and may span multiple lines. The line breaks are part
of the string. You can use quotation marks (") and backslashes (\)
inside a verbatim string without escaping them."""

Vala言語は文字列テンプレートをサポートしています。@"..."で囲われた文字列は、$記号を接頭辞にした式をその内容に含むことができます。
string name = "John";
stdout.printf (@"Welcome, $name!");
stdout.printf (@"3 + 2 = $(3 + 2)");

配列

動的な成長

Vala言語では、配列に対して+=演算子を用いて、動的に要素を追加していくことができます。配列は2のべき乗のサイズで(動的に)メモリー上に再配置されます。
int[] squares = {};
for (int i = 0; i < 100; i++) {
    squares += i * i;
}

境界はチェックしない

Vala言語では、いかなる場合にも、実行環境により配列の境界がチェックされることはありません。
int[] a = new int[10];
a[20] = 1;  // 危険なコード!
(Valaの将来のバージョンでは、任意の境界チェック機能を実装することが検討されています。)

多次元の配列

Javaの場合: ジャグ配列を使用できます。([][]。配列の配列です。)
int[][] matrix = new int[3][];
for (int[] row : matrix) {
    row = new int[4];
}

Valaの場合: 長方形配列を使用できます。(rectangular multi-dimensional arrays。 [,]、 [,,]。Javaにおける多次元配列は配列オブジェクトに対する参照を要素とする配列ですが、Valaにおけるそれは多次元配列そのものが1つの連続したメモリーブロックに配置されます。)Valaでも、ジャグ配列のサポートが予定されています。
int[,] matrix = new int[3,4];

型推論

Vala言語では、ローカル変数に関して、型推論(暗黙型決定)と呼ばれるメカニズムが適用されます。このメカニズムの下では、──変数の初期化の際の式からコンパイラが型を推論できる場合──ローカル変数は型名ではなくvarキーワードによって宣言できます。これにより、不要な冗長性(意訳:ソースコードの可読性に対してメリットにならない冗長性)が取り除かれ、ジェネリック型の使用が簡単になります。例えば以下のように──
var obj = new Object ();
var map = new HashMap<string, int> ();
var str = "hello, world";
var arr = new int[10];

これに対して型推論メカニズムがないと以下のようになります──
Object obj = new Object ();
HashMap<string, int> map = new HashMap<string, int> ();
string str = "hello, world";
int[] arr = new int[10];

もちろん、すべての変数は静的型システムの管理下にあります(Still, everything is statically typed。意訳:動的型システムとはちがいます)。

foreach文

Javaの場合: for (int i : numbers) { }

Valaの場合: foreach (int i in numbers) { }

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

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

JavaプログラマーからみたVala (1) ソースコード

最近なにかの拍子にVala言語に興味を持ってしまいました。Web上のドキュメントは限られているものの、Java言語との比較など平易なドキュメントもありましたので、学習をかねて稚拙な翻訳を載せていこうと思います。

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

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

JavaプログラマーからみたVala (1)

ソースファイル

Javaの場合: *.java

Valaの場合: *.vala

コンパイル

Javaの場合: JVMバイトコード(.classファイル)にコンパイルされます。
$ javac SourceFile1.java SourceFile2.java 
Valaの場合: C言語ソースコードに翻訳されたのち、ネイティブコードにコンパイルされます。
$ valac source1.vala source2.vala -o program 
Vala言語における標準オブジェクトシステムはGOjectであり、コンパイルされたValaライブラリは、有効なC言語ライブラリとなります。

ライブラリの使用

Javaの場合: .jarファイルを指定します。
$ javac -classpath foo-1.0.jar;bar-3.0.jar SourceFile.java 
Valaの場合: パッケージを指定します(.vapiファイルを介してCライブラリにアクセスします)
$ valac --pkg foo-1.0 --pkg bar-3.0 source.vala

Javaの場合:
  • クラス、インターフェース、列挙型: キャメルケース(パスカルケース)。
  • メソッド、ローカル変数、フィールド: ローワーキャメルケース。
  • 定数、列挙型インスタンス(enum values): アッパーケース(アンダーバーで結合)。
Valaの場合:
  • クラス、インターフェース、構造体、列挙型、デリゲート型、名前空間: キャメルケース(パスカルケース)。
  • メソッド、ローカル変数、フィールド、プロパティ、シグナル: ローワーケース(アンダーバーで結合)。
  • 定数、列挙型インスタンス: アッパーケース(アンダーバーで結合)。
名前にASCII文字以外の文字を使用することはできません。@を接頭辞として添えることで、名前にVala言語キーワード(予約語)を使用できます。この場合、@文字はそれを添えられた名前の一部としては認識されません。

ソースコードの組織化

ソースコード・ファイルについて

Javaの場合: 1つのファイルにつき、トップレベルのクラス(toplevel class。内部クラスでなく、パブリックなもの)は1つだけです。ファイル名はクラス名と一致します。

Valaの場合: 1つのファイルには複数のクラスを記述できます。ファイル名はクラス名と一致している必要はありません。

ヒエラルキーについて

Javaの場合: パッケージ概念があります。パッケージはディレクトリ構造によりあらわされます。またドメイン名を反転させた書式で構造化されます。
import javax.swing.*;

package org.foo.bar;

// ...
Valaの場合: 名前空間(namespaces)があります。ディレクトリ構造とは関係ありません。反転ドメイン名書式もとりません。
using Gtk;

namespace Foo.Bar {
    // ...
}
Valaの名前空間内には、所属クラスのないメソッドも存在します。これらは暗黙の静的メンバー(implicitly static)です。

デフォルトで読み込まれる名前空間について

Javaの場合: java.langパッケージ配下のクラスがデフォルトで読み込まれています。

Valaの場合: Glib名前空間がデフォルトで読み込まれています。

エントリーポイント

Javaの場合: public static void main(String[] args)

Valaの場合:  static int main (string[] args)

mainメソッドは、クラス外部で定義されても、privateアクセス修飾子が添えられていても、あるいは終了コード(exit code)としてintを返してもよいのです。その上argsはオプションです。

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

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

2010年8月22日日曜日

Maven2.2 で新しいプロジェクトを作成する

Windows環境においてMaven2.2で新しいプロジェクトを作成する方法についてメモ。

Maven2での同手順については、以下のサイトなど諸処で解説されている。

■プロジェクトの作成 - Maven-THECHSCOPE
http://www.techscore.com/tech/ApacheJakarta/Maven/2-2.html

■Maven Getting Started Guide - Apache Maven Project
http://maven.apache.org/guides/getting-started/index.html

ようするに、Mavenをローカルにインストールし、mvnコマンドを実行できる状態にまでした上で
mvn archetype:create
-DgroupId=com.mycompany.app
-DartifactId=my-app

か(Maven-THECHSCOPEの場合)、
mvn archetype:create
-DarchetypeGroupId=org.apache.maven.archetypes
-DgroupId=com.mycompany.app
-DartifactId=my-app
を(Apache Maven Projectの場合)、実行するのだけど、どちらにしても警告が出る。

まず、「archetype:create」の部分は、「archetype:generate」が正しい(Mavenのバージョンのちがいによるものと思われる)。
また前者のコマンドを実行した場合、プロジェクトの構築中に、
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
と表示されて、アーキタイプとそのバージョンを、数字で選択するよう促される。アーキタイプについては、「org.apache.maven.archetypes:maven-archetype-quickstart:1.0」がデフォルトのようだったが、これは環境や、直前の操作に影響されるものかもしれない。

前者のコマンドの場合、アーキタイプとバージョンへの回答が済むと、あとは放っておけばプロジェクトの作成が完了する。後者の場合は、アーキタイプの選択をせずとも作業は完了する。

また、こちらのサイトでも述べられていたが、どちらのコマンドもそのままではPowershell上で実行できない。コマンドプロンプトでは問題ないが、Powershell上で実行する場合は、「-D○○」系のオプションを1つ1つ、「"」(ダブルクオテーション)で囲う必要がある。
(そうしないと、コマンドの構文解析に失敗するらしく、どう足掻いてもエラーになる。)

つまり、こうなる。
mvn archetype:generate
"-DarchetypeGroupId=org.apache.maven.archetypes" (アーキタイプ・グループID)
"-DgroupId=com.m12i.myapp" (デフォルト・パッケージ名)
"-DartifactId=my-app" (作成するプロジェクト名)
※コマンドは、可読性のために改行を施したが、実際に実行する場合はこれらの改行はなくする。

2010年8月21日土曜日

Scalaを単体で実行可能なJarファイルにまとめる

【注】この記事の記述にはまちがいがありました。紹介されている参考記事の記述のうち、不要だったのは、マニフェストファイルでのクラスパス(Class-Path)の記述であって、scala-library.jarの展開は必須でした。

Scalaソースコードを、Javaクラスファイルにコンパイルしたあと、Scalaがインストールされていない環境でも(Java実行環境があれば)単体で実行可能なJarファイルにまとめる手順について。

jarコマンドとか、classpathとかそのへんすごい苦手なので、備忘録。
おおむね下記サイトに掲載されている通りでも問題ない。

■ScalaをJar化してみるComments - ゲーム作ろうよ
http://d.hatena.ne.jp/mitsu_chie/20100719/1279552867

だけど、要らない手順も含まれていたので、整理しておく。

1. Scalaソースコードを作成

ともかくmainメソッドを持つobject(シングルトンクラス)があればよいよね。
例えば、

HelloWorld.scala
object HelloWorld {
    def main (args: Array[String]): Unit = println("Hello world!")
}
とか。


2. scalacコマンドでJavaクラスファイルに変換

コマンドラインで、作成したScalaソースコード・ファイルを指定して
scalac HelloWorld.scala
この段階で、
scala HelloWorld
とコマンドを打てば、「Hello world!」とか表示されるはず。

3. scala-library.jarを用意する

scala-library.jarは、Scalaのインストール・ディレクトリに含まれる。
jarコマンドに長々とパスを指定したりしたくないので、scala-library.jarをコピーして、
Scalaソースコードと同じディレクトリにコピーする。


コマンドプロンプトで、
jar xf scala-library.jar
を実行して、scala-library.jarを展開する。結果的にフォルダ内にはscalaフォルダが新たに作られる。



4. マニフェスト・ファイルを作成

作成する実行可能Jarファイルの、実行時の設定を指定するため、マニフェスト・ファイルを用意する。

マニフェスト・ファイルでは、mainメソッドを持つクラス名(Scalaコード的にはobjectとして作ったもの)の名称と、Scalaコードから生成したクラスファイルを実行するために必要な、Scala APIのクラスを探索するクラスパスを指定する。

例えば、
manifest.mf
Manifest-Version: 1.0
Main-Class: HelloWorld
Class-Path: scala-library.jar
とか。
このファイルも便宜上、Scalaソースコードと同じディレクトリに 保存。

5. jarコマンドでアーカイブ

jarコマンドのオプションとして、

c(Jarファイルをつくるよ)
f(作成するJarファイル名を指定するよ)
m(マニフェスト・ファイルもあるよ)

を与え、
さらに、作成するJarファイルの名前と、作成したマニフェスト・ファイル名を指定。
最後に、新たにJarファイルとしてまとめることになるJavaクラスファイルやJarファイルを指定。

例えば、
jar cfm HelloWorld.jar manifest.mf *.class scala-library.jar
となる。
これで、このディレクトリ内のすべてのJavaクラスファイルと、scala-library.jarがまとめられてJarファイルHelloWorld.jarになる。
java -jar HelloWorld.jar
などとコマンドを打てば、「Hello world!」とか表示される。
Scalaコード内で呼び出しているScala APIによっては、jarコマンド末尾のアーカイブ化対象クラスファイルやJarファイルの一覧がながーくなっていくものと思われる。