java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

基本情報技術者試験平成31年度春期午後のJava問題で定義された列挙型について解説

投稿日:

最終更新日:2019年08月26日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

基本情報技術者試験平成31年度春期のJava問題を見て、そこに出てくるプログラム3が面白いと思ったので、解説を書いてみようと思いました。この記事では、回答部分を正解で埋めたプログラムを載せてますので、正解を知りたくない人は注意してください。

以下、最初に列挙型の復習を書き、最後に試験問題のプログラムについて書きます。

定数のみのenum型

Javaの列挙型はenum型と呼ばれるそうです。

一番単純なのは以下のような形式の宣言です。

定数だけのenum宣言

	public enum Direction {
		NORTH, EAST, SOUTH, WEST;
	}

上記のように宣言すると以下のように変数を定義して格納することが出来ます。

ソース

		Direction direction = Direction.NORTH;
		System.out.println(direction);

この場合、以下のように出力されます。

結果

NORTH

なぜこのような結果になるかというと、Enum型のtoString()メソッドが「宣言に含まれるとおりのenum定数の名前を返す」という仕様だからです。

メンバ変数とコンストラクタも定義できる

以下のようにコンストラクタを使う宣言も出来ます。

ソース

public enum Direction {

	NORTH(0, 1), EAST(1, 0), SOUTH(0, 1), WEST(-1, 0);

	public int dx, dy;

	private Direction(int dx, int dy) {
		this.dx = dx;
		this.dy = dy;
	}

}

上記の定数の宣言はコンストラクタを使う宣言方法です。

以下のような使い方が出来ます。

ソース

		Direction direction = Direction.NORTH;

		System.out.println(direction.toString());
		System.out.println(direction.dx);
		System.out.println(direction.dy);

結果

NORTH
0
1

上記のプログラムは試験問題に登場したenum型のコンストラクタとメンバ変数の部分です。駒が向いている方向のベクトルを定義しているようです。駒が1回に進むマスの相対的な位置ともいえます。たとえば、Direction.NORTHはy座標を「+1」というニュアンスです。

メソッドも定義できる

以下が試験問題のプログラム3です。回答部分を埋めてあります。

ソース

public enum Direction {
	NORTH(0, 1), EAST(1, 0), SOUTH(0, 1), WEST(-1, 0);

	public int dx, dy;

	private Direction(int dx, int dy) {
		this.dx = dx;
		this.dy = dy;
	}


	public Direction left() {
		return values()[(ordinal() + 3) % 4];
	}

	public Direction right() {
		return values()[(ordinal() + 1) % 4];
	}

}

「出典:平成31年度 春期 基本情報技術者試験 午後 問11」

上記のようにメソッドを宣言できます。

メソッドを呼び出したときの実際の動作例は以下です。

ソース

		Direction direction = Direction.NORTH;

		System.out.println(direction.toString());
		System.out.println(direction.dx);
		System.out.println(direction.dy);

		direction = direction.right();
		System.out.println(direction.toString());
		System.out.println(direction.dx);
		System.out.println(direction.dy);

結果

NORTH
0
1
EAST
1
0

上記はright()メソッドを使った例です。メソッド名が表すように、右方向に向きを変えるという機能のメソッドです。

一行で記述されているので初見では戸惑うかも知れませんが、次のように書き換えるとわかりやすいと思います。

ソース

		// 全ての定数の配列を取得
		Direction[] directions = values();

		// 要素番号を計算
		int index = (ordinal() + 1) % 4;

		// 返却
		return directions[index];

values()メソッドは暗黙的なメソッドで、「列挙型のすべての定数を取得する」ことが出来ます。このメソッドは配列を返却します。なので、「values()[x];」と書けば、要素番号xの要素ということになります。詳しくは分かりませんが、「[]」は配列要素を参照する演算子なのでこのように記述できるという事のようです。

また、ordinal()メソッドは定義した定数の列挙宣言での位置を返却します。一番最初は0です。4つの定数を定義しているので、「+1」のあと「%4」をしています。4で割った余りを求めているので、計算式の結果は「0, 1, 2, 3」だけとなります。3の次は0に戻るという感じの計算式です。

right()メソッドは、上記のように、配列の要素をリターンしていて、その要素はちょうど右方向を向いた向きに対応する定数ということです。