対象:C言語経験者 / 試験問2の3大テーマです。概念と試験でのキーワードを整理します
フィールドを private にして外部から直接アクセスできなくし、public なメソッド経由でのみ操作させる仕組みです。
前の単元で「p1.age = 999; とできてしまう」という問題がありました。これをカプセル化で防ぎます。
class Person {
private String name; // private:外部から直接アクセス不可
private int age;
Person(String name, int age) {
this.name = name;
this.age = (age >= 0) ? age : 0; // 不正な値を弾ける
}
// getter:値を取り出すメソッド
public String getName() { return name; }
public int getAge() { return age; }
// setter:値を設定するメソッド(検証できる)
public void setAge(int age) {
if (age >= 0) this.age = age; // 負の値は無視
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person("Taro", 20);
// p.age = -5; // コンパイルエラー(private)
p.setAge(21); // setterを通すのでOK
System.out.println(p.getName() + " : " + p.getAge());
}
}
既存のクラスのフィールドとメソッドを引き継いで、新しいクラスを作る仕組みです。extends キーワードを使います。
// スーパークラス(親)
class Animal {
String name;
Animal(String name) {
this.name = name;
}
void eat() {
System.out.println(name + " は食べます。");
}
}
// サブクラス(子):Animal を継承
class Dog extends Animal {
Dog(String name) {
super(name); // 親のコンストラクタを呼ぶ
}
void bark() {
System.out.println(name + " はワンと吠えます。");
}
}
public class Main {
public static void main(String[] args) {
Dog d = new Dog("ポチ");
d.eat(); // 親から引き継いだメソッド
d.bark(); // Dog 独自のメソッド
}
}
| 用語 | 内容 | 別名 |
|---|---|---|
| 継承元のクラス | 既存のクラス。フィールドとメソッドを提供します | スーパークラス・親クラス・基底クラス |
| 継承先のクラス | 新しく作るクラス。既存のクラスを拡張します | サブクラス・子クラス・派生クラス |
extends | 継承を宣言するキーワード | — |
super() | 親のコンストラクタを呼ぶ | — |
親クラスのメソッドを子クラスで上書きすることです。オーバーロード(引数違いの同名メソッド)とは別の概念なので混同しないようにしましょう。
class Animal {
void speak() {
System.out.println("...");
}
}
class Dog extends Animal {
@Override // オーバーライドであることを明示(省略可だが書くのが慣習)
void speak() {
System.out.println("ワン!");
}
}
class Cat extends Animal {
@Override
void speak() {
System.out.println("ニャー!");
}
}
| オーバーロード | オーバーライド | |
|---|---|---|
| 場所 | 同じクラス内 | 親クラスと子クラス |
| 引数 | 型・数が違う | 同じ |
| 目的 | 同名で異なる処理を定義 | 親の処理を子で上書き |
「同じ操作(メソッド呼び出し)をしても、インスタンスの種類によって異なる動作をする」性質です。
Animal a1 = new Dog("ポチ"); // 親型の変数に子インスタンスを入れられる
Animal a2 = new Cat("タマ");
a1.speak(); // → ワン!(Dog の speak が呼ばれる)
a2.speak(); // → ニャー!(Cat の speak が呼ばれる)
// 配列にまとめて処理できる
Animal[] animals = { new Dog("ポチ"), new Cat("タマ"), new Dog("シロ") };
for (Animal a : animals) {
a.speak(); // それぞれ異なるメソッドが動く
}
実習:継承とオーバーライドを動かす
10_OOP フォルダに OOPMain.java を作って実行しましょう。
class Shape {
String color;
Shape(String color) {
this.color = color;
}
double area() {
return 0; // サブクラスでオーバーライドする
}
void show() {
System.out.printf("%s の面積: %.2f%n", color, area());
}
}
class Circle extends Shape {
double radius;
Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
double width, height;
Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
public class OOPMain {
public static void main(String[] args) {
Shape[] shapes = {
new Circle("赤い円", 5.0),
new Rectangle("青い長方形", 4.0, 6.0),
new Circle("緑の円", 3.0)
};
for (Shape s : shapes) {
s.show();
}
}
}
試験(問2)との対応
| 用語 | 意味 |
|---|---|
| カプセル化 | データを隠蔽してメソッド経由でのみアクセスさせること |
| 継承(インヘリタンス) | 既存クラスを引き継いで新クラスを作ること |
| スーパークラス | 継承元(親)のクラス |
| サブクラス | 継承先(子)のクラス |
| ポリモーフィズム(多態性) | 同じ操作でもインスタンスの種類によって動作が変わること |
| メッセージ | インスタンスへのメソッド呼び出し(a.speak() など) |
| 概念 | 一言まとめ |
|---|---|
| カプセル化 | private でデータを隠して、public メソッドで操作させます |
| 継承 | extends で親クラスを引き継ぎます |
| オーバーライド | 子クラスで親のメソッドを上書きします(@Override を付けます) |
| ポリモーフィズム | 親型の変数に子インスタンスを入れて、異なる動作をさせます |