9-2. クラス・インターフェース・継承
このセクションで学ぶこと
Section titled “このセクションで学ぶこと”- クラスの定義方法(フィールド・コンストラクタ・メソッド)を習得する
- アクセス修飾子によるカプセル化の実装を理解する
- 継承(
extends)とオーバーライドの仕組みを学ぶ - インターフェース(
implements)と抽象クラスの使い分けを理解する - record によるデータクラスの簡潔な宣言方法を知る
第4章でオブジェクト指向の概念(カプセル化・継承・ポリモーフィズム)を学んだ。ここではJavaでの具体的な実装方法を習得する。
クラスとオブジェクト
Section titled “クラスとオブジェクト”// クラスの定義public class Book { // フィールド(インスタンス変数) private String title; private String author; private int price;
// コンストラクタ public Book(String title, String author, int price) { this.title = title; this.author = author; this.price = price; }
// メソッド public String getTitle() { return title; } public String getAuthor() { return author; } public int getPrice() { return price; }
public void setPrice(int price) { if (price < 0) throw new IllegalArgumentException("価格は0以上である必要があります"); this.price = price; }
public String describe() { return String.format("『%s』 著者: %s, 価格: %d円", title, author, price); }
// toString のオーバーライド @Override public String toString() { return describe(); }}
// オブジェクトの生成と使用Book book = new Book("Java入門", "田中", 2800);System.out.println(book.getTitle()); // "Java入門"System.out.println(book.describe()); // 『Java入門』 著者: 田中, 価格: 2800円System.out.println(book); // toString() が呼ばれるアクセス修飾子
Section titled “アクセス修飾子”アクセス修飾子と可視性┌─────────────┬─────────┬─────────┬───────────┬────────────┐│ 修飾子 │ 同クラス │ 同パッケ │ サブクラス │ 全てのクラス││ │ │ ージ │ │ │├─────────────┼─────────┼─────────┼───────────┼────────────┤│ private │ ✅ │ ❌ │ ❌ │ ❌ ││ (なし) │ ✅ │ ✅ │ ❌ │ ❌ ││ protected │ ✅ │ ✅ │ ✅ │ ❌ ││ public │ ✅ │ ✅ │ ✅ │ ✅ │└─────────────┴─────────┴─────────┴───────────┴────────────┘フィールドは private、外部アクセスが必要なものはメソッドで公開するのが基本(カプセル化)。
static フィールドとメソッド
Section titled “static フィールドとメソッド”public class Counter { private static int count = 0; // クラス全体で共有 private int id;
public Counter() { count++; this.id = count; }
public static int getCount() { return count; } // インスタンスなしで呼べる public int getId() { return id; }}
Counter c1 = new Counter();Counter c2 = new Counter();System.out.println(Counter.getCount()); // 2(static メソッドはクラス名で呼ぶ)System.out.println(c1.getId()); // 1System.out.println(c2.getId()); // 2record(Java 16以降)
Section titled “record(Java 16以降)”データを保持するだけのクラスは record で簡潔に書ける。
// 通常のクラス(コンストラクタ・getter・equals・hashCode・toString が冗長)// → record で自動生成
public record Point(int x, int y) {}
Point p = new Point(3, 4);System.out.println(p.x()); // 3System.out.println(p.y()); // 4System.out.println(p); // Point[x=3, y=4]p.equals(new Point(3, 4)); // true// 基底クラス(スーパークラス)public class Animal { protected String name;
public Animal(String name) { this.name = name; }
public void speak() { System.out.println(name + " が何か言った"); }
public String getName() { return name; }}
// 派生クラス(サブクラス)public class Dog extends Animal { private String breed;
public Dog(String name, String breed) { super(name); // 親のコンストラクタを呼ぶ this.breed = breed; }
@Override // オーバーライドを明示(付けないとコンパイラが警告を出せない) public void speak() { System.out.println(name + " がワンワンと吠えた"); }
public String getBreed() { return breed; }}
// 使用例Dog dog = new Dog("ポチ", "柴犬");dog.speak(); // "ポチ がワンワンと吠えた"dog.getName(); // "ポチ"(親のメソッドを継承)
Animal animal = dog; // アップキャスト(Animalとして扱える)animal.speak(); // "ポチ がワンワンと吠えた"(実際のオブジェクトのメソッドが呼ばれる)instanceof と型チェック
Section titled “instanceof と型チェック”Animal animal = new Dog("ポチ", "柴犬");
if (animal instanceof Dog dog) { // Java 16以降のパターンマッチング System.out.println(dog.getBreed()); // "柴犬"}
// 古い書き方if (animal instanceof Dog) { Dog d = (Dog) animal; System.out.println(d.getBreed());}final クラスとメソッド
Section titled “final クラスとメソッド”// final クラス:継承禁止public final class Immutable { ... }
// final メソッド:オーバーライド禁止public class Base { public final void cannotOverride() { ... }}
// String クラスは final → 継承できないインターフェース
Section titled “インターフェース”インターフェースは「何ができるか」という契約を定義する。Javaでは複数インターフェースを実装できる(クラスは単一継承のみ)。
// インターフェース定義public interface Printable { void print(); // 抽象メソッド(実装なし)
// デフォルトメソッド(Java 8以降):実装を持てる default void printWithBorder() { System.out.println("---"); print(); System.out.println("---"); }}
public interface Saveable { void save(String filename);}
// インターフェースの実装public class Document implements Printable, Saveable { private String content;
public Document(String content) { this.content = content; }
@Override public void print() { System.out.println(content); }
@Override public void save(String filename) { System.out.println(filename + " に保存しました"); }}
// 使用例Document doc = new Document("Hello, Java!");doc.print(); // "Hello, Java!"doc.printWithBorder(); // "---\nHello, Java!\n---"doc.save("test.txt"); // "test.txt に保存しました"
// インターフェース型として扱える(ポリモーフィズム)Printable p = new Document("Hi");p.print();継承 vs インターフェース
Section titled “継承 vs インターフェース”使い分けの基準┌─────────────┬──────────────────────────────────────────┐│ 継承 │ 「AはBの一種である」(is-a) 関係 ││ │ 例:Dog extends Animal │├─────────────┼──────────────────────────────────────────┤│ インター │ 「Aはこの機能を持つ」(can-do) 関係 ││ フェース │ 例:Document implements Printable │└─────────────┴──────────────────────────────────────────┘継承を前提とした「一部だけ実装したクラス」。インターフェースとクラスの中間的な存在。
public abstract class Shape { protected String color;
public Shape(String color) { this.color = color; }
// 抽象メソッド:サブクラスで必ず実装する public abstract double area();
// 通常のメソッド:サブクラスに共通の実装を提供 public void describe() { System.out.printf("色: %s, 面積: %.2f%n", color, area()); }}
public class Circle extends Shape { private double radius;
public Circle(String color, double radius) { super(color); this.radius = radius; }
@Override public double area() { return Math.PI * radius * radius; }}
public class Rectangle extends Shape { private double width, height;
public Rectangle(String color, double width, double height) { super(color); this.width = width; this.height = height; }
@Override public double area() { return width * height; }}
// 使用例Shape[] shapes = { new Circle("赤", 5.0), new Rectangle("青", 4.0, 6.0),};
for (Shape s : shapes) { s.describe(); // ポリモーフィズム:実際のオブジェクトの area() が呼ばれる}// 色: 赤, 面積: 78.54// 色: 青, 面積: 24.00| 概念 | キーワード | 説明 |
|---|---|---|
| クラス | class | フィールドとメソッドを持つ設計図 |
| カプセル化 | private + getter/setter | 内部状態を隠蔽し、メソッドで公開 |
| 継承 | extends | 親クラスの機能を引き継ぐ(単一継承) |
| オーバーライド | @Override | 親クラスのメソッドを再定義する |
| インターフェース | implements | 「できること」の契約(複数実装可) |
| 抽象クラス | abstract | 一部だけ実装した、継承前提のクラス |
| record | record | データ保持クラスの簡潔な宣言 |