MENU

PHPの基本から応用まで – 初心者向けチュートリアルシリーズ(第4回:オブジェクト指向プログラミング基礎)

目次

はじめに

前回の関数とスコープの解説に続き、今回はPHPにおけるオブジェクト指向プログラミング(OOP)の基礎について学んでいきます。OOPは、コードをより整理された、再利用可能な形で書くための重要な概念です。

クラスとオブジェクト

クラスの基本

<?php
class User {
    // プロパティ(クラスの変数)
    private $name;
    private $email;
    private $age;
    
    // コンストラクタ
    public function __construct(string $name, string $email, int $age) {
        $this->name = $name;
        $this->email = $email;
        $this->age = $age;
    }
    
    // メソッド(クラスの関数)
    public function getName(): string {
        return $this->name;
    }
    
    public function getEmail(): string {
        return $this->email;
    }
    
    public function getAge(): int {
        return $this->age;
    }
}

オブジェクトの作成と使用

// オブジェクトのインスタンス化
$user = new User("山田太郎", "yamada@example.com", 25);

// メソッドの呼び出し
echo $user->getName() . "\n";    // 出力: 山田太郎
echo $user->getEmail() . "\n";   // 出力: yamada@example.com
echo $user->getAge() . "\n";     // 出力: 25

アクセス修飾子

PHPには3つのアクセス修飾子があります:

  1. public: クラスの外部からアクセス可能
  2. private: 同じクラス内からのみアクセス可能
  3. protected: 同じクラスと子クラスからアクセス可能
class Product {
    public $name;          // 外部からアクセス可能
    private $price;        // クラス内部のみ
    protected $category;   // 継承したクラスでも使用可能
    
    public function __construct(string $name, int $price, string $category) {
        $this->name = $name;
        $this->price = $price;
        $this->category = $category;
    }
    
    // privateプロパティにアクセスするためのメソッド
    public function getPrice(): int {
        return $this->price;
    }
}

継承

クラスの機能を別のクラスに引き継ぐことができます:

class User {
    protected $name;
    protected $email;
    
    public function __construct(string $name, string $email) {
        $this->name = $name;
        $this->email = $email;
    }
}

class AdminUser extends User {
    private $accessLevel;
    
    public function __construct(string $name, string $email, int $accessLevel) {
        parent::__construct($name, $email);
        $this->accessLevel = $accessLevel;
    }
    
    public function hasFullAccess(): bool {
        return $this->accessLevel >= 5;
    }
}

インターフェースと抽象クラス

インターフェース

interface PaymentInterface {
    public function processPayment(float $amount): bool;
    public function refund(float $amount): bool;
}

class CreditCardPayment implements PaymentInterface {
    public function processPayment(float $amount): bool {
        // クレジットカード決済の処理
        return true;
    }
    
    public function refund(float $amount): bool {
        // 返金処理
        return true;
    }
}

抽象クラス

abstract class Vehicle {
    protected $brand;
    
    abstract public function start();
    
    public function getBrand(): string {
        return $this->brand;
    }
}

class Car extends Vehicle {
    public function __construct(string $brand) {
        $this->brand = $brand;
    }
    
    public function start() {
        echo "エンジンを始動します\n";
    }
}

実践的な例:ECサイトの商品管理システム

<?php
interface PricingInterface {
    public function calculatePrice(): float;
    public function applyDiscount(float $percentage): void;
}

abstract class BaseProduct {
    protected $name;
    protected $basePrice;
    protected $stock;
    
    public function __construct(string $name, float $basePrice, int $stock) {
        $this->name = $name;
        $this->basePrice = $basePrice;
        $this->stock = $stock;
    }
    
    abstract public function getType(): string;
}

class PhysicalProduct extends BaseProduct implements PricingInterface {
    private $weight;
    private $shippingCost;
    private $discountRate = 0;
    
    public function __construct(
        string $name, 
        float $basePrice, 
        int $stock,
        float $weight,
        float $shippingCost
    ) {
        parent::__construct($name, $basePrice, $stock);
        $this->weight = $weight;
        $this->shippingCost = $shippingCost;
    }
    
    public function getType(): string {
        return '物理商品';
    }
    
    public function calculatePrice(): float {
        $price = $this->basePrice + $this->shippingCost;
        if ($this->discountRate > 0) {
            $price -= ($price * $this->discountRate);
        }
        return $price;
    }
    
    public function applyDiscount(float $percentage): void {
        $this->discountRate = $percentage / 100;
    }
}

// 使用例
$product = new PhysicalProduct("テストProduct", 1000, 10, 0.5, 500);
echo "商品タイプ: " . $product->getType() . "\n";
echo "通常価格: " . $product->calculatePrice() . "円\n";

$product->applyDiscount(20);  // 20%割引を適用
echo "割引後価格: " . $product->calculatePrice() . "円\n";

注意点とベストプラクティス

  1. 単一責任の原則
    • 各クラスは1つの責任のみを持つべき
    • 必要に応じて適切に分割する
  2. カプセル化
    • プロパティは原則privateかprotectedにする
    • アクセサメソッド(getter/setter)を使用する
  3. 依存性の注入
    • 外部のクラスやサービスは、コンストラクタで注入する
    • 疎結合なコードを心がける
  4. SOLID原則の適用
    • Single Responsibility(単一責任)
    • Open/Closed(開放/閉鎖)
    • Liskov Substitution(リスコフの置換)
    • Interface Segregation(インターフェース分離)
    • Dependency Inversion(依存性逆転)

まとめ

今回は、PHPのオブジェクト指向プログラミングの基礎について学びました。クラス、継承、インターフェース、抽象クラスなどの概念を理解することで、より構造化されたコードが書けるようになります。

練習問題

  1. 銀行口座を表すクラスを作成してください。以下の機能を実装してください:
    • 残高の取得と設定
    • 入金と出金の処理
    • 残高不足時のエラー処理
  2. 従業員管理システムを作成してください:
    • 基本的な従業員クラス
    • 正社員とパートタイム従業員を表す子クラス
    • 給与計算のインターフェース
    • 各種従業員タイプに応じた給与計算の実装

次回は、PHPにおけるデータベース操作について解説していきます。お楽しみに!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次