Kotlinの良いところ

adventar.org

Muroran Institute of Technology Advent Calendar 2017

Dec. 18

Kotlin のここが良い

Kotlinという名前

「Kotlinは可愛い.」

初めてその名を見た時,私はそれがプログラミング言語であるとは気付かなかった. Kotlinを書き始めて数週間,私は,Kotlinは実はキメラなのではないかと思い始めた. 現在,私はKotlinの魔力に囚われている.

実行または開発環境

  • JVM上で動く
  • 環境構築が楽
  • Javaのライブラリを利用できる
  • Androidアプリも開発できるらしい

KotlinはJetBrainsで開発されたJVM向けの言語です. IntelliJ IDEAをインストールするとKotlinをすぐに使うことができます. したがって,環境構築は非常に楽です.

また,Kotlinで書いたコードはコンパイルされた後,Javaと同様にJVM上で実行されます. さらに,JavaのライブラリをKotlinのプログラムから利用することもできます. Gradleのプラグインも存在しており,これを使用したMavenのライブラリの利用も可能です.

ちなみに,私は試していませんが,Androidアプリも開発できるようです.

文法に関して

Javaの無駄を排除
  • nullは無駄
  • セミコロンは無駄
  • newは無駄
  • 変数宣言時の型名は無駄
  • main関数にとってクラスは無駄

Javaによるプログラミングにおいて,nullは諸悪の根源であり, これを駆逐するためにはnullチェックを欠かしてはいけません. しかし,これほど面倒臭いことがありましょうか? そして,そもそもnullは必要なのでしょうか? Haskellを見れば,変数が無くても,プログラムを作成することが可能であると分かります. 読み取り専用の変数をnullで初期化することに意味は無く, したがって,読み取り専用の変数はnull以外の値で初期化されます. また,全ての変数が読み取り専用でもプログラムは正しく動くことが可能です. すなわち,nullを用いずともプログラムは正しく動くのです. nullは不要です. それどころか,バグの根またはnullチェックの手間以外の何物でも無いのです.

Kotlinにはnonnull型とnullable型があります. nonnull型の変数にnullを代入し,またはnullで初期化しようとするとコンパイルエラーとなります. このnull安全な文法により,プログラマは憎っくきnullに触ることなくコードを書くことができます. このnull安全性は私がScalaではなくKotlinを選ぶ決め手となりました.

1行に複数の文が存在する事は稀で,そもそも,そういう書き方は好まれません. 実際,Pythonは改行で文を区切ることとなっています. すなわち,文末のセミコロンは不要なのです.

Java, C++等では,当たり前のように何千何万何億ものセミコロンを書いてきましたが, Kotlinではその無駄な作業をせずに済むのです.

Javaにおいて,オブジェクト生成時にはコンストラクタの呼び出しおよびnewを記述しなければいけません. コンストラクタの呼び出しを見れば,生成するオブジェクトのクラスおよび呼び出すコンストラクタに渡す引数といった, オブジェクト生成に必要な全ての情報が分かります. では,newを見るとどんな情報が得られるでしょうか,いいえ,どんな情報も得られません. Javaにおいて,newは不要なはずなのです. Kotlinでは,この無駄も排除されるのです. 私はこの点においてKotlinはJavaおよびScalaより良いと思っています.

変数宣言時の型名を省略しても良い言語が多く存在します. Kotlinもその一つです. C++にもautoができましたね. Javaにおいて,なぜ1つの変数宣言で同じ型名を2度も書かなければならないのかと思った事はありませんか? 明らかに無駄な型名を書かなくてはいけないというJavaの苦しみから,型推論があなたを解放します.

Hello World!を書くためだけになぜクラスを作らなければいけないのか,なぜ標準出力 (System.out.println("Hello World!");)がめんどくさいのか? KotlinはC++のように関数をクラス外に書けます. ついでに言うと,標準出力もprintln("Hello World!")とシンプルです.

ここまでの内容をまとめると,

  1. Javaには記述の無駄が多い.
  2. Kotlinはそれらの無駄を削ぎ落としたものとなっている.

と言えるのではないでしょうか.

不変性のサポート
  • val
  • デフォルトの修飾子

不変クラスはクラスの理想の姿と言えます. スレッドセーフであり,意図しない変更を受けず,矛盾した状態となることもないからです. 例えば,不変クラスのインスタンスへの参照を保持する読み取り専用の変数は, いつでもどこでも初期化時と同じ値を保つため,取り扱いが非常に楽です. プログラムを書くときは,不変クラスを作成したり,変数を読み取り専用としたりことによって, できるだけ不変とすることが望ましいと思います.

しかし,Javaにおいて,これは生易しい話ではありません. 全ての変数にfinalを付けていく作業は心の折れる作業です. また,不変クラスを作成する際は,そのクラスのインスタンスが保持するオブジェクトが変更されないことを保証しなければいけません. これを実現するためには

  • 継承不可とする.
  • フィールドを読み取り専用とする.
  • 可変なオブジェクトを変更しない.
  • 可変なオブジェクトの参照を共有しない.

といったことに注意しなければいけません.

ここで,不変クラスは推奨されていますが,Javaでの実装が困難であるという問題があります. これに対して,Kotlinには不変性を意識したプログラミングを援護する文法があり, 不変クラスの実装を楽に行えます.

例えば,変数を宣言する時にval a = 1と書くと,変数aは読み取り専用となります. これはfinal int a = 1;をとするより,シンプルです.

また,クラスおよびメソッドはデフォルトでfinalが付いた状態となっております. 継承可能とするためまたはオーバーライド可能とするためにはopenを付けます. そして,C++とは逆に,アクセス指定はデフォルトでpublicとなります. はじめのうち,私は,カプセル化に反する感じがして慣れませんでした. しかし,よく考えると, フィールドはプロパティによってラップされているので, オブジェクトが不変である場合には困る事はありませんでした.

以上のように,Kotlinは言語として不変性をサポートしてくれます.

その他の便利機能
  • 演算子オーバーロード
  • 分解宣言
  • data class
  • 関数のデフォルト引数と名前付き引数
  • when式, if else式, throw catch式
  • Iterableの拡張関数

ここではKotlinの文法に関するその他の良いところを挙げていきます. まず,演算子オーバーロードです. やはり,ベクトル,点その他の数学的なクラスは数値型の演算子を同じように使いたくなります. そんなときに,演算子オーバーロードができる言語はありがたいです.

KotlinのクラスはcomponentN()を実装することで, オブジェクトの値を分解して,複数の変数を同時に初期化することができます.

class Vector(val x: Double, val y: Double, val z: Double) {
    operator fun component1(): Double = x
    operator fun component2(): Double = y
    operator fun component3(): Double = z
}

fun main(vararg args: String) {
    val (a, b, c) = Vector(1.0, 2.0, 3.0)
    println("$a, $b, $c")
    //1.0, 2.0, 3.0
}

さらに,Kotlinにはdata classというものがあり, 単に

data class Vector(val x: Double, val y: Double, val z: Double)

と書くだけで,Javaのよくある次のようなクラスに

public final class Vector {

    private final double x;

    private final double y;

    private final double z;

    public Vector(double x, double y, double z){
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public double getZ() {
        return z;
    }

    @Override
    public String toString() {
        return "Vector(x="x + ", y=" + y + ", z=" + z + ")";
    }
}

を実装したクラスに更に operator fun component1(): Double = x, operator fun component2(): Double = yおよびoperator fun component3(): Double = z を実装したこととなります.

Javaにおいて,例えば,コンストラクタなどで設定すべき引数が多くなってくると, 引数の順番が分からない,デフォルトの設定がある,といった事態が起きます. そんなときは組み合わせ爆発によりオーバーロードに限りがありません. その結果として,Builderを作ることとなるのではないでしょうか? Kotlinでは,以下のように,関数のデフォルト引数および名前付き引数を利用することができます.

data class Vector(val x: Double = 0.0, val y: Double = 0.0, val z: Double = 0.0)

fun main(vararg args: String) {
    println(Vector(1.0, 2.0, 3.0))
    //Vector(1.0, 2.0, 3.0)
    println(Vector(1.0, 2.0))
    //Vector(1.0, 2.0, 0.0)
    println(Vector())
    //Vector(0.0, 0.0, 0.0)
    println(Vector(y = 2.0))
    //Vector(0.0, 2.0, 0.0)
    println(Vector(1.0, z = 3.0))
    //Vector(1.0, 0.0, 3.0)
    println(Vector(z = 3.0, y = 2.0))
    //Vector(0.0, 2.0, 3.0)
}

そして,Kotlinでは条件分岐のためのwhenおよびif elseならびに例外処理のためのtry catchが全て式となり値を持ちます. これらを値を持つ式として扱えば条件漏れなどを無くせるのではないでしょうか?

他に,Kotlinには拡張関数という機能があり,これによってIterableのメソッドが便利になっています. 以下にその例を挙げます.

  • filter
  • map
  • zip
  • take
  • drop
  • reduce
  • fold
  • sortedBy
  • zipWithNext
  • find

ここでは私が気に入っている機能について紹介させていただきました.

Bezier 曲線を描くならどっち?

KotlinとJavaで,どちらの方が楽にプログラムを書けそうか比べてみます. ここでは,Bezier曲線クラスの実装を例にします.

Bezier曲線とは

\(n\)次のBezier曲線 \( \boldsymbol{B} : [0, 1] \to \mathrm{E} \) はパラメータ\(t \in [0, 1]\)に対応する点\(\boldsymbol{B}(t) \in \mathrm{E}\)を返す関数で, \(n + 1\)個の制御点\(\boldsymbol{p}_{i} \ (0 \leq i \leq n)\)を用いて,

$$\boldsymbol{B}(t) = \boldsymbol{B}_{0}^{n}(t)$$

と評価します.ただし,

$$\boldsymbol{B}_{i}^{0}(t) = \boldsymbol{p}_{i} \ (0 \leq i \leq n)$$ $$\boldsymbol{B}_{i}^{j}(t) = (1-t) \boldsymbol{B}_{i}^{j-1}(t) + t \boldsymbol{B}_{i+1}^{j-1}(t) \ (1 \leq j \leq n, 0 \leq i \leq n - j)$$

です.

Intervalクラス

package jumpaku.kotlin

data class Interval(val begin: Double, val end: Double){

    operator fun contains(t: Double): Boolean = t in begin..end
}
package jumpaku.java;

public final class Interval {
    public Interval(final double begin, final double end) {
        this.begin = begin;
        this.end = end;
    }

    private final double begin;

    private final double end;

    public double getBegin() {
        return begin;
    }

    public double getEnd() {
        return end;
    }

    public boolean contains(final double t) {
        return begin <= t && t <= end;
    }

    @Override
    public String toString() {
        return String.format("jumpaku.kotlin.Interval(begin=%.1f, end=%.1f)", begin, end);
    }
}

Pointクラス

package jumpaku.kotlin

data class Point(val x: Double = 0.0, val y: Double = 0.0) {

    fun divide(t: Double, that: Point): Point {
        return Point(x.divide(t, that.x), y.divide(t, that.y))
    }

    private fun Double.divide(t: Double, that: Double): Double {
        return (1-t)*this + t*that
    }
}
package jumpaku.java;

import java.util.Objects;

public final class Point{

    public Point(final double x, final double y) {
        this.x = x;
        this.y = y;
    }

    public static Point ofX(final double x) {
        return new Point(x, 0.0);
    }

    public static Point ofY(final double y) {
        return new Point(0.0, y);
    }

    public static Point origin() {
        return new Point(0.0, 0.0);
    }

    private final double x;

    private final double y;

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public Point divide(final double t, final Point that) {
        Objects.requireNonNull(that);
        return new Point(divide(t, x, that.x), divide(t, y, that.y));
    }

    private double divide(final double t, final double d0, final double d1) {
        return (1-t)*d0 + t*d1;
    }

    @Override
    public String toString() {
        return String.format("jumpaku.kotlin.Point(x=%.1f, y=%.1f)", x, y);
    }
}

BezierCurveクラス

package jumpaku.kotlin

class BezierCurve(vararg controlPoints: Point){

    val controlPoints: List<Point>

    init {
        require(controlPoints.isNotEmpty()) { "control point is empty" }
        this.controlPoints = listOf(*controlPoints)
    }

    val domain: Interval = Interval(0.0, 1.0)

    fun evaluate(t: Double): Point {
        require(t in domain) { "t($t) is out of domain($domain)" }
        return decasteljau(t, controlPoints)
    }

    private fun decasteljau(t: Double, controlPoints: List<Point>): Point {
        return when {
            controlPoints.size == 1 -> controlPoints.first()
            else -> decasteljau(t, controlPoints.zipWithNext { a, b -> a.divide(t, b) })
        }
    }
}
package jumpaku.java;

import java.util.*;

public final class BezierCurve {

    public BezierCurve(Point... controlPoints) {
        Objects.requireNonNull(controlPoints);
        if (controlPoints.length == 0) {
            throw new IllegalArgumentException("control point is empty");
        }
        if (Arrays.stream(controlPoints).anyMatch(Objects::isNull)){
            throw new IllegalArgumentException("control point contains null");
        }
        this.controlPoints = Collections.unmodifiableList(Arrays.asList(controlPoints));
    }

    private final List<Point> controlPoints;

    private final Interval domain = new Interval(0.0, 1.0);

    public List<Point> getControlPoints() {
        return new ArrayList<>(controlPoints);
    }

    public Interval getDomain() {
        return domain;
    }

    public Point evaluate(double t) {
        if (!domain.contains(t)) {
            throw new IllegalArgumentException("t($t) is out of domain($domain)");
        }
        return decasteljau(t, controlPoints);
    }

    private Point decasteljau(final double t, final List<Point> points) {
        if (points.size() == 1) {
            return points.get(0);
        }
        else {
            ArrayList<Point> result = new ArrayList<>();
            for (int i = 0; i < points.size() - 1; i++) {
                result.add(points.get(i).divide(t, points.get(i + 1)));
            }
            return decasteljau(t, result);
        }
    }
}

動作実験

Kotlinのソースコード

package jumpaku.kotlin

fun main(vararg args: String) {
    println("Jumpaku")

    val bezierCurve = BezierCurve(
            Point(-1.0, -1.0),
            Point(-1.0, 1.0),
            Point(1.0, -1.0),
            Point(1.0, 1.0))
    (0..4).map { i -> i/4.0 }
            .map { bezierCurve.evaluate(it) }
            .map { (x, y) -> "$x, $y" }
            .forEach(::println)
}

実行結果

-1.0, -1.0
-0.6875, -0.125
0.0, 0.0
0.6875, 0.125
1.0, 1.0

Javaソースコード

package jumpaku.java;

import java.util.stream.IntStream;

public class Main {

    public static void main(String... args) {
        System.out.println("Jumpaku");

        BezierCurve bezierCurve = new BezierCurve(
                new Point(-1.0, -1.0),
                new Point(-1.0, 1.0),
                new Point(1.0, -1.0),
                new Point(1.0, 1.0));
        IntStream.rangeClosed(0, 4)
                .mapToDouble(i -> i/4.0)
                .mapToObj(t -> bezierCurve.evaluate(t))
                .map(p -> p.getX() + ", " + p.getY())
                .forEach(System.out::println);
    }
}

実行結果

-1.0, -1.0
-0.6875, -0.125
0.0, 0.0
0.6875, 0.125
1.0, 1.0

JavaとKotlinで同じ実行結果を出力するプログラムを書きましたが, Kotlinの方がシンプルで良いと思います. また,ソースコードはどちらも同じ設計に基づいていることも感じられると思います.

まとめ

Kotlinについて思ったことをひたすら書きました. 私は,KotlinはJavaと同じパラダイムの言語でありながら, Javaの無駄を削ぎ落とし, 推奨される書き方をサポートし, 様々な言語の良い部分を寄せ集めた言語であると思います.

Javaを使っている人,特に,室蘭工業大学情報系のあなた,是非Kotlinを使ってみてください.

Python で論理クイズ Solve Logic Quiz with Python

はじめに

Python は手軽に書けるスクリプト言語です. 論理クイズは与えられた説明と矛盾しない解答を論理的に導くクイズです. 今回は Python を使って論理クイズを解きます.

Python

文法が分かりやすく,シンプルに書くことができ,標準ライブラリも充実していて,とても使いやすいと感じています. 今回は itertools モジュールを使って,組み合わせを総当りすることによって,論理クイズを解きます.

論理クイズ

ここで扱う論理クイズでは,初期設定と容疑者達の証言をもとに事件の真相を論理的に導きます.

初期設定とは容疑者の集合および嘘つきの人数であり,最初に与えられます.

証言とは事件に関する主張を1つ以上並べたもので,容疑者は最大で1つの証言を行います.

嘘つきとは容疑者のうち,証言をし,それが真相と矛盾するような人物のことです.

正直者とは容疑者のうち,嘘つきではない人物のことです.

真相とは1人の真犯人と0人以上の嘘つきの組み合わせのうち,初期設定,嘘つきの証言の否定および正直者の証言のどれとも矛盾しない唯一のものです.

ソースコード

次のソースコードは論理クイズを解く Python3 のプログラムです. suspectsは容疑者とその証言を表します. 容疑者名をキーとし,lambda 式を値とする辞書で実装します. ここで,lambda 式は嘘つきの名前のタプルおよび犯人の名前を受け取り,証言の真偽を返します. liarsCountは嘘つきの人数です.

このプログラムは容疑者の中から犯人を1人選ぶ組み合わせおよび嘘つきを人数分選ぶ組み合わせの直積の中から, 初期設定,嘘つきの証言の否定および正直者の証言のどれとも矛盾しないものを標準出力に出力します. 出力されるものが1つならそれが真相です.

# -*- coding: utf-8 -*-
import itertools as it

def implies(p, q):
    return (not p) or q

def give_testimony(testimony, is_liar):
    return not testimony if is_liar else testimony

# 容疑者名と証言の辞書
suspects = {}
# 嘘つきの人数
liarsCount = 0

for truth in it.product(
        it.combinations(suspects.keys(), liarsCount),
        suspects.keys()):
    liars, criminal = truth
    isConsistent = all([give_testimony(t(liars, criminal), s in liars)
                        for s, t in suspects.items()])
    if isConsistent:
        print("嘘つきは{},犯人は{}.".format("と".join(liars), criminal))

実行

今回は説法系推理アドベンチャシリーズの3つのゲーム,

で出題される論理クイズを解きます. これらのゲームは私が作成し,ウディフェスまたはウディコンにエントリしたゲームです. 以下ではこれらのゲームのネタバレがあります. 未プレイの方は以下の文章を読む前に,プレイするかプレイ動画を見てください.

愛と血の修羅場(サスペンス)

嘘つきは1人,容疑者と証言をまとめると以下のようになります.

  • 恵伊 : 史衣と出井は嘘をつかず,史衣と出井は犯人ではない.
  • 美衣 : 恵伊と良威のどちらかは正直者.
  • 史衣 : 犯人は出井か恵伊.
  • 出井 : 出井と美衣はどちらも犯人ではない.
  • 良威 : 犯人は美衣.

本ゲームで正解となる真相は,「嘘つきは良威,犯人は恵伊.」です.

上のプログラムのsuspectsおよびliarsCount

#容疑者名と証言の辞書
suspects = {
    "恵伊": lambda ls, c: ("史衣" not in ls) and ("出井" not in ls) and ("史衣" != c) and ("出井" != c),
    "美衣": lambda ls, c: ("恵伊" not in ls) or ("良威" not in ls),
    "史衣": lambda ls, c: ("恵伊" == c) or ("出井" == c),
    "出井": lambda ls, c: ("美衣" != c) and ("史衣" != c),
    "良威": lambda ls, c: ("美衣" == c)
}
#嘘つきの人数
liarsCount = 1

と初期化し,実行すると,嘘つきは良威,犯人は恵伊.と出力されます. よって,「嘘つきは良威,犯人は恵伊.」が唯一の真相であることが確認できます.

恋と友情の常識(ファイト)

嘘つきは2人,容疑者と証言をまとめると以下のようになります.

  • 恵伊 : 良威は正直者.
  • 美衣 : 恵伊は嘘つきではない,または史衣は嘘つきではない.
  • 史衣 : 出井は嘘つき.
  • 出井 : 美衣と恵夫はどちらも犯人ではない.
  • 良威 : 犯人は恵夫.
  • 恵夫 : 良威は嘘つき.

本ゲームで正解となる真相は「嘘つきは出井と恵夫,犯人は恵夫.」です.

上のプログラムのsuspectsおよびliarsCount

#容疑者名と証言の辞書
suspects = {
    "恵伊": lambda ls, c: "良威" not in ls,
    "美衣": lambda ls, c: ("恵伊" not in ls) or ("史衣" not in ls),
    "史衣": lambda ls, c: "出井" in ls,
    "出井": lambda ls, c: ("美衣" != c) and ("恵夫" != c),
    "良威": lambda ls, c: "恵夫" == c,
    "恵夫": lambda ls, c: "良威" in ls,
}
#嘘つきの人数
liarsCount = 2

と初期化し,実行すると,嘘つきは出井と恵夫,犯人は恵夫.と出力されます. よって,「嘘つきは出井と恵夫,犯人は恵夫.」が唯一の真相であることが確認できます.

罪と幸せの四苦八苦(ノアズアーク)

嘘つきは2人,容疑者と証言をまとめると以下のようになります.

  • 美衣 : 犯人は嘘つきの中の誰かで,出井は犯人ではない.
  • 史衣 : 犯人は恵夫.
  • 出井 : 永一と史衣はどちらも嘘つき.
  • 恵夫 : (証言無し)
  • 永一 : 出井が正直者ならば出井は犯人ではなく,美衣は正直者.

本ゲームで正解となる真相は「嘘つきは史衣と出井,犯人は史衣」です.

上のプログラムのsuspectsおよびliarsCount

#容疑者名と証言の辞書
suspects = {
    "美衣": lambda ls, c: (c in ls) and ("出井" != c),
    "史衣": lambda ls, c: "恵夫" == c,
    "出井": lambda ls, c: ("永一" in ls) and ("史衣" in ls),
    "恵夫": lambda ls, c: True,
    "永一": lambda ls, c: implies("出井" not in ls, "出井" != c) and ("美衣" not in ls),
}
#嘘つきの人数
liarsCount = 2

と初期化し,実行すると,嘘つきは史衣と出井,犯人は史衣.と出力されます. よって,「嘘つきは史衣と出井,犯人は史衣」が唯一の真相であることが確認できます.

まとめ

辞書やリストをシンプルに記述でき,その取り扱いも標準ライブラリが充実しているため,とても楽でした. PyCharmで書けば,静的チェックもしてくれたので,助かりました.

罪と幸せの四苦八苦(ノアズアーク)

仲間達との船旅で起こる悲劇.
船上で発見された仲間の死体.
容疑者達は己の信じる愛を貫く.
すれちがう証言と譲れない主張.
私は論理の果てに真実をつかむ.

ゲーム情報

本ゲームは登場人物の説法を聞くことと,論理クイズを組み合わせた説法系推理アドベンチャです.

  • タイトル : 罪と幸せの四苦八苦(ノアズアーク)
  • 読み : つみとしあわせののあずあーく
  • 作者 : Jumpaku
  • ジャンル : 説法系推理アドベンチャ
  • プレイ時間 : 30分程度
  • プラットフォーム : Windows
  • リリース : 2017年7月24日
  • 言語 : 日本語
  • 開発環境 : WOLF RPGエディター

遊び方 How to play

上のリンクからダウンロードしてください.

ゲームを始めるには"Game.exe"を実行して下さい. 詳しい操作方法は"README.pdf"を読んで下さい.

ウディコンにエントリ

このゲームをウディコン2017に提出しました.

コンテストのページはここです. WOLF RPGエディターコンテスト -ウディコン- / 力作フリーゲーム!

ヴァージョン Version

  • v1.3 : 誤字の訂正
  • v1.2 : 誤字脱字の訂正
  • v1.1 : README.pdfの間違いを訂正
  • v1.0 : 最初の完成品

リンク

±ZERO

f:id:Jumpaku:20170722214902j:plain

離れていると死んでしまう!!

紹介

私はProject ZEROという友人のゲーム開発に参加しました. そこで"±0" というゲームを作って,ウディコン2017に参加したので宣伝します.

このゲームは離れていると死んでしまう2人のキャラクタを切り替えながら, ダンジョンを攻略し,ストーリーを進めていくRPGです. ダンジョンには様々なギミックがあり,その攻略にはパズルを解く面白さがあります.

ウディコン2017のページからダウンロードして遊べます. https://www.silversecond.com/WolfRPGEditor/Contest/entry.shtml

ゲーム情報

リンク

Gradle でライブラリを追加 Add libraries with Cradle

Gradle とは

Gradle とは Ant や Maven にかわるビルドツールです. Maven などに比べて, ビルドスクリプトがシンプルになり, 見やすい気がします. また, Mavenリポジトリのライブラリを利用することができます.

Gradle の準備

NetBeans

NetBeansでGradleを利用するためにプラグインをインストールします. “ツール” –> “プラグイン” –> “使用可能なプラグイン” –> “Gradle Support” を選択し, “インストール” を押します.

Intellij

Intellij では最初から Gradle を利用することができます.

Gradle プロジェクトの作成

新しく自分の Gradle プロジェクトを作成する方法を説明します.

NetBeans

“ファイル” –> “新しいプロジェクト” –> “Gradle” –> “Single Gradle Project” –> “次” と進み, “Project Name” などを埋め, “終了” を押すと Gradle プロジェクトが作成されます.

Intellij

“New” –> “Project” –> “Gradle” –> “Java” と進み,
“GroupId”, “ArtifactId” および “Version” を埋め, “Next” –> “Next” と進んで,
“Project name” および “Project Location” を埋め, “Finish” を押すと Gradle プロジェクトが作成されます.

このとき, 自分のプロジェクトの “GroupId”, “ArtifactId” および “Version” が必要となる場合はそれらを自分で決めます.

依存性の追加

依存性とはプロジェクトで使用する外部のライブラリです. 自分のプロジェクトで使用したい外部のライブラリを自分のプロジェクトへ追加する方法を説明します.

まず, Google などを利用して, 使用する外部のライブラリのグループID, アーティファクトIDおよびバージョンを調べます.

プロジェクト内のbuild.gradleファイルのdependencies { }の中に, 調べた情報を次のように書き加えます.

dependencies {
    //使いたいライブラリの情報を調べておいて,
    //ここに書き加える.
    compile group: 'グループID', name: 'アーティファクトID', version: 'バージョン'
}

Gradle プロジェクトのオープン

Gradle プロジェクトを IDE で開くときに, 開きたいプロジェクトのbuild.gradleファイルを指定します.