午後問題の歩き方 | Java プログラミング問題の楽勝パターン(2)オブジェクト指向


2022-06-07 更新

error

この記事は基本情報技術者試験の旧制度( 2022 年以前)の記事です。
この記事の題材となっている「午後問題」は現在の試験制度では出題されません。 ご注意くださいませ。

前回の記事では、「 C 言語と Java のどちらかを選択する予定だ」という人に、

「試験当日の問題次第ですが、生半可に Java ができるというレベルでは、Java を選ばない方が無難かもしれませんね」

というアドバイスをしました。

Java プログラミング問題の難易度(1)Java 基本構文

ただし、「ぜひ Java を選んでください!」とアドバイスしたくなるような問題もあります。

それは、 継承や多態性などのオブジェクト指向がテーマの問題 です。オブジェクト指向が苦手でないなら、きっと楽勝のはずです。

実際の問題を見てみましょう。

info本記事では読みやすいよう、シンタックスハイライトを入れています。実際の試験では白黒です。ご注意くださいませ。

infoスマートフォンでご覧の際は、プログラムは横スクロールできます

抽象クラスや抽象メソッドを知っていれば楽勝

以下は、平成 29 年度 春期 午後 問 11「電気料金プランの比較」 の設問 1 の一部です。

プログラムの説明は省略しますが、空欄 a に入るものを解答群から選んでください。

[プログラム 1]

'[ 空欄a ]' class TierTable {
	final double[][] pairs;

	TierTable(double... tiers) {
		if (tiers.length % 2 == 1) {
			throw new IllegalArgumentException("不正な長さ: " + tiers.length);
		}
		double[][] a = new double[tiers.length / 2][];
		for (int i = 0; i < tiers.length; i += 2) {
			a[ '[ 空欄b ]' ] = new double[] { tiers[i], tiers[i + 1] };
		}
		this.pairs = a;
	}

	abstract double map(double amount);
}
a に関する解答群

ア abstract  
イ final  
ウ private
エ protected  
オ public  
カ static

 

TierTable クラスには、 abstract double map(double amount); という抽象メソッドがあります。

抽象メソッドを持つクラスは、インスタンスを生成できないので、class の前に abstract を指定して抽象クラスにしなければなりません。

したがって、正解は、選択肢アです。

いかがですか。「えっ! こんなに簡単でいいの?」と言いたくなるような問題でしょう。

 

ただし、そう思えるのは、オブジェクト指向の概念である抽象クラスや抽象メソッドを知っているからです。

継承を知っていれば楽勝

以下は、同じ年度の問題の設問 2 の一部です。プログラムの説明を読んで、空欄eに入るものを解答群から選んでください。

 プログラム 6 は,割引プランを表すためのクラス DiscountPlan である。 DiscountPlan は,クラス RatePlan を拡張し,上位クラスである RatePlan のメソッド getPrice で求めた電気料金から割引率を求め,割引を適用した金額を電気料金として計算する。プログラム中の       に入れる正しい答えを,解答群の中から選べ。

[プログラム 6 ]

class DiscountPlan '[ 空欄e ]' RatePlan {
	private final TierTable discountTiers;

	Discount Plan(String name, double basicCharge,
					TierTable pricingTiers, TierTable discountTiers) {
		super (name, basicCharge, pricingTiers);
		this.discountTiers = discountTiers;
	}

	int getPrice(double amount) {
		int price = '[ 空欄f ]'.getPrice(amount);
		return (int) (price * '[ 空欄g]' );
	}
}
e に関する解答群

ア extends  
イ implements  
ウ imports
エ public  
オ throws

プログラムの説明に「 DiscountPlan は、クラス RatePlan を拡張し」と示されています。これは、「 RatePlan クラスを継承して DiscountPlan クラスを定義する」という意味です。

Java では、継承 を extends(拡張する) というキーワードで示します。したがって、正解は、選択肢アです。

これも、「えっ! こんなに簡単でいいの?」と言いたくなるような問題でしょう。

 

ただし、そう思えるのは、オブジェクト指向の概念である継承を知っているからです。( 2 回目)

PR

継承におけるコンストラクタの取り扱いを知っていれば楽勝

今度は、平成 26 年度 春期 午後 問 11「雑誌記事のオンライン購読サイト」 の設問 1 の一部です。プログラムの説明は省略しますが、空欄 b に入るものを解答群から選んでください。

[プログラム 5 ]

class PaidMember extends Member {
	PaidMember(String name) {
		'[ 空欄b ]';
	}

	boolean testAndMark(Article article) {
		return '[ 空欄d ]';
	}
}

b に関する解答群

ア new User(name)  イ super()  ウ super(name)
エ super.name = name  オ this()  カ this(name)
キ this.name = name  ク User(name)

 

class PaidMember extends Member { } という構文から、Member クラスを継承して PaidMember クラスを定義しています。

PaidMember クラスの中にある PaidMember(String name) { } は、クラス名と同名のメソッドなので、コンストラクタ です。

多くの場合に、コンストラクタ では、引数の値をフィールドに格納する処理が行われます。

ここでは、引数 name を何らかのフィールドに指定するはずです。ところが、PaidMember クラスには、フィールドがありません。

なぜでしょう。

フィールドは、継承元の Member クラスにあるからです。

それでは、継承元の Member クラスのフィールドに 引数 name の値を渡すには、どうしたらよいでしょう。

選択肢をヒントにして考えてみましょう。

super(name); という構文で、継承元のクラスのコンストラクタを呼び出せばよいことに気づくはずです。正解は、選択肢ウです。

 

これも、オブジェクト指向の概念である継承と、継承におけるコンストラクタの取り扱いを知っていれば、楽勝の問題です。

クラスの継承とインターフェイスの実装の違いを知っていれば楽勝

続いて、平成 24 年 秋期 午後 問 11「スレッドを利用したタイマ」 の設問 1 の一部です。ここでも、プログラムの説明は省略しますが、空欄 c に入るものを解答群から選んでください。

[プログラム 1]

public interface TimerAction {
	public void onStart(Timer timer, long instant);
	public void onAlarm(Timer timer, long instant);
	public void onCancel(Timer timer, long instant);
}

[プログラム 3]

import java.util.Date;

public class TimerTest '[ 空欄c ]' TimerAction {
	Timer longTimer, shortTimer;

	private void test() '[ 空欄d ]' InterruptedException {
		longTimer = Timer.createTimer("long timer", '[ 空欄e ]', 4);
		shortTimer = Timer.createTimer("short timer", '[ 空欄e ]', 2);
		shortTimer.close();
		longTimer.close();
	}
	// 中略
}
c, d に関する解答群

ア expands  
イ extends  
ウ implements
エ subclasses  
オ throw  
カ throws

TimerAction は、クラスではなくインターフェイスです。クラスは extends キーワードで継承しますが、インターフェイスは implements キーワードで実装する ものです。

ここでは、TimerTest クラスが TimerAction インターフェイスを実装します。したがって、空欄 c に入るのは、選択肢ウの implements です。

 

ついでに、空欄 d に入るものも選んでみましょう。

public void test() の後に空欄 d があり、その後に InterruptedException という例外クラスが指定されています。

これは、「 test() メソッドが InterruptedException 例外を投げる」という表現です。したがって、空欄 d には、選択肢カの throws が入ります。

 

この空欄 d は、オブジェクト指向に直接関係していませんが、Javaの例外に関する構文を知っていれば、楽勝のはずです。こういう問題も出るのです。

インターフェイスを使った多態性を知っていれば楽勝

最後に、もう 1 つだけ楽勝の問題を紹介しましょう。

以下は、平成 23 年度 春期(特別試験)午後 問 11「追加可能な文字列インターフェイスの 2 種類の実装」 の一部です。

プログラムを示しませんが、AppendableCharSequence インターフェイスと、それを実装した ArrayAppendableCharSequence クラス、および ListAppendableCharSequence クラスがあります。

同じインターフェイスで定義されたメソッドを、2つのクラスが実装(メソッドの処理内容をそれぞれのクラスに合わせて記述)しているのです。

これは、多態性 です。

 

以下に示したプログラムの空欄 e には、引数 a に、ArrayAppendableCharSequence クラスのインスタンスと、ListAppendableCharSequence クラスのインスタンスの、どちらでも指定できるデータ型を入れることになります。

それは、AppendableCharSequence インターフェイスです。同じインターフェイスを実装したクラスのインスタンスは、そのインターフェイスをデータ型とすることができます。

これは、多態性を使ったプログラムで定番の表現です。知っていれば、楽勝! 楽勝です!

[プログラム 4 ]

public class Test {
	static final int[] TIMES = {
		5000, 10000, 50000, 100000
	};

	public static void main(String[] args) {
		for (int n : TIMES) {
			measureTime(n, new ArrayAppendableCharSequence());
			measureTime(n, new ListAppendableCharSequence());
		}
	}

	static void measureTime(int n, '[ 空欄e ]' a ) {
		long start = System.currentTimeMillis();
		for (int i = 0; i < n; i++) {
			a.append((char) (i % 26 + 'a'));
		}
		long end = System.currentTimeMillis();
		System.out.printf("%s: %d [times] %d [ms]%n",
						a.getClass().getName(),
						n, end - start);
	}
}

e に関する解答群

ア AppendableCharSequence
イ ArrayAppendableCharSequence
ウ ListAppendableCharSequence
エ ListAppendableCharSequence.Bucket
オ Object
カ String

 

今回の記事では、「オブジェクト指向が苦手でないなら楽勝」という問題を紹介しましたが、C 言語より Java の方が常に楽勝なわけではありません。

C 言語と Java のどちらかを選択する予定の人は、試験当日の問題の内容を見て、慎重に判断してください。

中途半端に Java に手を付けてから「やっぱり C 言語に変えよう」とならないように、くれぐれも注意してください。時間を大幅にロスしてしまうからです。

 

それでは、またお会いしましょう!

 

label 関連タグ
科目A試験は、
免除できます。
独習ゼミで科目A試験を1年間免除して、科目B試験だけに集中しましょう。
免除試験を受けた 74.9% の方が、
科目A免除資格を得ています。
科目A免除試験 最大 2 回の
受験チャンス !
info_outline
科目A免除試験 最大 2 回の
受験チャンス !
詳しく見てみるplay_circle_filled
label これまでの『午後問題の歩き方』の連載一覧 label 著者