オブジェクト指向プログラミング(OOP)の概要
オブジェクト指向プログラミングは、ソフトウェアシステムを「オブジェクト」という自律的な単位の集合としてモデル化する設計思想です。現実世界の事物や概念をオブジェクトとして表現し、それらの相互作用によってシステム全体を構築します。JavaにおいてOOPを理解する上で、中核となる3つの要素「カプセル化」、「継承」、「ポリモーフィズム(多態性)」の把握は不可欠です。
カプセル化
カプセル化は、オブジェクトの内部状態(データ)と実装詳細を外部から隠蔽し、必要な操作のみを公開する仕組みです。これにより、外部からの不正なアクセスや予期せぬ状態変更を防ぎ、システムの保守性と安全性を高めることができます。具体的には、フィールドをprivate修飾子で保護し、publicなメソッド(アクセサ)を通じてのみデータの操作を許可します。
public class BankAccount {
private double balance;
private String owner;
public BankAccount(String owner, double initialBalance) {
this.owner = owner;
if (initialBalance >= 0) {
this.balance = initialBalance;
} else {
throw new IllegalArgumentException("初期残高は正の数である必要があります");
}
}
public double getBalance() {
return this.balance;
}
public void deposit(double amount) {
if (amount > 0) {
this.balance += amount;
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
} else {
System.out.println("出金処理が失敗しました:残高不足または無効な金額");
}
}
}
継承
継承は、既存のクラス(スーパークラス/親クラス)の属性や振る舞いを、新しいクラス(サブクラス/子クラス)が引き継ぐ機能です。これにより、共通のコードを再利用しつつ、サブクラス固有の機能を追加したり、既存の機能を変更したりすることが可能になります。Javaではextendsキーワードを使用して継承関係を定義します。
class Vehicle {
protected String brand;
public Vehicle(String brand) {
this.brand = brand;
}
public void startEngine() {
System.out.println(brand + "のエンジンが始動しました");
}
}
class ElectricCar extends Vehicle {
private int batteryLevel;
public ElectricCar(String brand, int batteryLevel) {
super(brand);
this.batteryLevel = batteryLevel;
}
public void charge() {
System.out.println("バッテリーを充電中です...");
this.batteryLevel = 100;
}
}
ポリモーフィズム(多態性)
ポリモーフィズムは、同じインターフェースやメソッド呼び出しに対して、異なるオブジェクトがそれぞれ異なる振る舞いをすることを指します。これにより、具体的なクラスの型に依存せず、スーパークラスやインターフェースの型としてプログラミングできるため、コードの柔軟性と拡張性が大幅に向上します。Javaではメソッドのオーバーライドやインターフェースの実装を通じてこれを実現します。
interface NotificationService {
void sendNotification(String message);
}
class EmailNotification implements NotificationService {
@Override
public void sendNotification(String message) {
System.out.println("メール送信: " + message);
}
}
class SMSNotification implements NotificationService {
@Override
public void sendNotification(String message) {
System.out.println("SMS送信: " + message);
}
}
public class NotificationSystem {
public static void main(String[] args) {
NotificationService emailService = new EmailNotification();
NotificationService smsService = new SMSNotification();
notifyUser(emailService, "システムアップデートが完了しました");
notifyUser(smsService, "認証コードは1234です");
}
public static void notifyUser(NotificationService service, String msg) {
service.sendNotification(msg);
}
}
実際の開発における活用シナリオ
これら3つの特性は、実際のエンタープライズレベルのアプリケーション開発において頻繁に組み合わせて使用されます。カプセル化によりデータの整合性を保ち、継承によってコードの重複を排除し、ポリモーフィズムによってアルゴリズムの切り替えや機能拡張を容易にします。
| 特性 | 活用シーン | 実装アプローチ | コード例 |
|---|---|---|---|
| カプセル化 | アプリケーション設定管理 | 1. 設定値をprivateフィールドで保持 2. 読み取り専用アクセサの提供 3. イミュータブルな設計パターンの適用 |
private final String apiKey; |
| セッション状態管理 | 1. セッションIDの非公開 2. 有効期限チェックのロジック隠蔽 |
public boolean isActive() { |
|
| 継承 | 例外処理の共通化 | 1. 基底例外クラスの作成 2. エラーコード等の共通フィールド定義 3. 特定の例外ごとのサブクラス化 |
abstract class BaseException extends Exception { |
| UIコンポーネントライブラリ | 1. 基底コンポーネント(描画、イベント) 2. ボタンやテキストボックスでの機能拡張 |
class Button extends UIComponent { |
|
| ポリモーフィズム | データ永続化層の実装 | 1. Repositoryインターフェースの定義 2. SQL、NoSQLごとの実装クラス 3. 実行時の切り替え |
interface DataRepository { |
| 支払い決済モジュール | 1. 決済戦略インターフェースの定義 2. クレジットカード、電子マネー等の実装 3. 注文処理における動的選択 |
PaymentStrategy strategy = new CreditCardPayment(); |