7日目のゴール
7日目のテーマは
「クラス分割の考え方を使って、“自分で小さなアプリを設計しきる”こと」 です。
ここまでであなたはすでに、
クラスは役割を持った登場人物
main はスタート地点であり、シナリオを書く人
フィールド・コンストラクタ・メソッドで役割を形にする
処理のかたまりに名前をつけて、ふさわしいクラスに置く
という感覚を、買い物アプリやタスク管理アプリで体に入れてきました。
7日目では、
「最初から最後まで、自分でクラス構成を考える」 ことをやります。
題材は、現実でもイメージしやすい「図書館の貸出ミニアプリ」です。
今日の題材:図書館貸出ミニアプリを“言葉だけ”で設計する
まずはコードを書かずに、登場人物を洗い出す
いきなり Java に行かず、
現実の世界をそのまま眺めるところから始めます。
図書館でやっていることを、ざっくり言葉にするとこうです。
本がある
利用者がいる
利用者が本を借りる・返す
「今誰がどの本を借りているか」を管理する
ここから、クラス候補を取り出します。
本を表すクラス
利用者を表すクラス
貸出状況を管理するクラス
アプリ全体の流れを書く main
Java のクラス名にすると、こうなります。
Book … 本1冊を表す
User … 利用者1人を表す
Library … 本と貸出状況をまとめて管理する
Main … Library や User を使って、シナリオを書く
この「現実 → クラス」の変換を、自分でできるようになっているかが、7日目の一番大事なポイントです。
Book クラスを設計する
「本1冊」をちゃんと1人前のクラスにする
まずは、本1冊を表すクラスから。
public class Book {
private String title;
private String author;
private boolean borrowed;
public Book(String title, String author) {
this.title = title;
this.author = author;
this.borrowed = false;
}
public void borrow() {
borrowed = true;
}
public void giveBack() {
borrowed = false;
}
public boolean isBorrowed() {
return borrowed;
}
public String getTitle() {
return title;
}
public void show() {
String status = borrowed ? "[貸出中]" : "[在庫あり]";
System.out.println(status + " 「" + title + "」 (" + author + ")");
}
}
Javaここでの重要ポイントを深掘りします。
コンストラクタで「タイトルと著者」を必須にしているnew Book("走れメロス", "太宰治") のように、
「タイトルも著者もない本」が作れないようにしています。
作られた瞬間に borrowed = false(まだ借りられていない)という正しい初期状態になります。
borrow と giveBack で状態変更をカプセル化している
外から book.borrowed = true; のように直接いじらせず、
「借りる」「返す」という“意味のある操作”として提供しています。
show が「自分の表示の仕方」を知っている
Book 自身が「自分をどう表示するか」を知っているので、
他のクラスは book.show(); と呼ぶだけで済みます。
Book の役割を一言で言うと、
「本1冊の情報と、その貸出状態を管理するクラス」 です。
User クラスを設計する
「利用者1人」を表すクラス
次に、利用者を表すクラスです。
今回はシンプルに、「名前だけ持つ人」として扱います。
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Java今はあえて、User は「名前を持つだけ」にしています。
貸出処理は Library に任せる設計にします。
User の役割を一言で言うと、
「利用者の名前を表すだけの、シンプルな登場人物」 です。
Library クラスを設計する
「本と貸出状況をまとめて管理する人」
ここが今日のメインディッシュです。
Library は、「本の一覧」と「貸出・返却の操作」を担当します。
public class Library {
private Book[] books;
private int count;
public Library(int maxSize) {
books = new Book[maxSize];
count = 0;
}
public void addBook(Book book) {
if (count >= books.length) {
System.out.println("これ以上本を追加できません。");
return;
}
books[count] = book;
count++;
}
public void showAllBooks() {
System.out.println("=== 蔵書一覧 ===");
if (count == 0) {
System.out.println("本が登録されていません。");
return;
}
for (int i = 0; i < count; i++) {
System.out.print((i + 1) + ". ");
books[i].show();
}
}
public void showAvailableBooks() {
System.out.println("=== 貸出可能な本 ===");
boolean hasAny = false;
for (int i = 0; i < count; i++) {
if (!books[i].isBorrowed()) {
System.out.print((i + 1) + ". ");
books[i].show();
hasAny = true;
}
}
if (!hasAny) {
System.out.println("貸出可能な本はありません。");
}
}
public void borrowBook(int index, User user) {
if (!isValidIndex(index)) {
System.out.println("その番号の本は存在しません。");
return;
}
Book book = books[index];
if (book.isBorrowed()) {
System.out.println("「" + book.getTitle() + "」はすでに貸出中です。");
return;
}
book.borrow();
System.out.println(user.getName() + " さんが「" + book.getTitle() + "」を借りました。");
}
public void returnBook(int index, User user) {
if (!isValidIndex(index)) {
System.out.println("その番号の本は存在しません。");
return;
}
Book book = books[index];
if (!book.isBorrowed()) {
System.out.println("「" + book.getTitle() + "」はもともと貸出中ではありません。");
return;
}
book.giveBack();
System.out.println(user.getName() + " さんが「" + book.getTitle() + "」を返却しました。");
}
private boolean isValidIndex(int index) {
return index >= 0 && index < count;
}
}
Javaここでの本質を丁寧に整理します。
Library は「本の配列」と「現在の冊数」を内側に持っている
配列やカウンタは private にして、外から直接いじれないようにしています。
外からは「本を追加」「一覧表示」「貸出」「返却」といった“意味のある操作”だけをお願いできます。
addBook が「蔵書を増やす」という操作になっている
配列のどこに入れるか、カウンタをどう増やすか、
そういった細かい実装は Library の中に閉じ込めています。
borrowBook と returnBook が「User と Book の橋渡し」をしている
User は「誰が借りたか」を表し、
Book は「借りられているかどうか」を知っていて、
Library がその間を取り持っています。
showAvailableBooks が「貸出可能な本だけを表示する」という意味のある操作になっている
「配列を回して、借りられていない本だけを表示する」という細かい処理を、
Library の中に閉じ込めています。
main は「いつ呼ぶか」だけを考えればよくなります。
Library の役割を一言で言うと、
「本の一覧と貸出・返却のルールをまとめて管理するクラス」 です。
main は“シナリオを書く人”として締めくくる
登場人物を new して、流れだけを書く
ここまでのクラスを使って、7日目の main を書きます。
public class Main {
public static void main(String[] args) {
Library library = new Library(10);
Book b1 = new Book("走れメロス", "太宰治");
Book b2 = new Book("こころ", "夏目漱石");
Book b3 = new Book("銀河鉄道の夜", "宮沢賢治");
library.addBook(b1);
library.addBook(b2);
library.addBook(b3);
User user = new User("太郎");
System.out.println("最初の状態:");
library.showAllBooks();
System.out.println();
System.out.println("貸出可能な本:");
library.showAvailableBooks();
library.borrowBook(0, user);
library.borrowBook(2, user);
System.out.println();
System.out.println("貸出後の状態:");
library.showAllBooks();
library.returnBook(0, user);
System.out.println();
System.out.println("一部返却後の状態:");
library.showAllBooks();
}
}
Javamain がやっていることを、言葉で整理します。
Library を1つ作る
Book をいくつか作って、Library に登録する
User を1人作る
「いつ一覧を表示するか」「どの本を借りるか・返すか」という流れを書く
ここで重要なのは、
main は「本が貸出中かどうか」のフラグを知らない
配列の添字や冊数の管理にも踏み込んでいない
Book・User・Library の public メソッドだけを使って、シナリオを書いている
という構造になっていることです。
7日目で、自分の頭の中に持っておいてほしい“図”
ここまで来たあなたに、
クラスと main の関係を、こうイメージしてほしいです。
Book
本1冊の情報と貸出状態を管理する。
「借りる」「返す」「自分を表示する」ことができる。
User
利用者1人を表す。
今回は名前だけ持つ、シンプルな登場人物。
Library
本の一覧と貸出・返却のルールを管理する。
「本を追加」「一覧表示」「貸出可能な本の表示」「貸出・返却」を担当する。
Main
これらのクラスを new して、
「どの本を用意するか」「誰がどの本を借りるか」というシナリオを書く。
中身の実装には踏み込まず、public メソッドだけを使う。
この「説明できるかどうか」が、
7日間の学びがちゃんと自分のものになっているかの、最後のチェックポイントです。
7日目で絶対に押さえてほしい本質
今日いちばん大事なのは、
「自分で題材を決めて、クラスの役割と main との関係を設計しきれた」 という経験です。
現実の世界から登場人物(クラス)を見つける
それぞれに「一言で言える役割」を与える
フィールド・コンストラクタ・メソッドで、その役割を形にする
main は「登場人物を new して、順番を決める」だけにする
そして、ずっと共通していた問いはこれです。
「この処理は誰の責任か?」
「この処理に名前をつけるとしたら?」
「その名前が一番しっくりくるクラスはどれか?」
ここまで7日間やり切ったあなたは、
もう「クラスをなんとなく書く人」ではなく、
“クラス分割という道具で、小さなアプリを設計できる人” です。
あとは、この感覚を別の題材にもどんどん当てはめていくだけ。
ゲームでも、家計簿でも、予約システムでも、
「登場人物を見つけて、役割を決めて、main からシナリオを書く」——
その流れは、もうあなたの中にちゃんと根づいています。

