Основы PHP: Объектно-ориентированное программирование (ООП)
PHP предоставляет мощные возможности для объектно-ориентированного программирования, начиная с версии 5.
Основные концепции ООП
- Класс (Class): Чертеж или шаблон для создания объектов. Он определяет свойства (атрибуты) и поведение (методы), которыми будут обладать объекты этого класса.
- Объект (Object): Экземпляр класса. Объект обладает свойствами, определенными классом, и может выполнять методы, определенные в классе.
- Свойство (Property) или Атрибут: Переменная, принадлежащая объекту. Представляет состояние объекта.
- Метод (Method): Функция, принадлежащая объекту. Определяет поведение объекта.
- Инкапсуляция (Encapsulation): Сокрытие внутренней реализации объекта и предоставление контролируемого доступа к его данным и методам через публичный интерфейс. Это помогает предотвратить случайное изменение внутреннего состояния объекта.
- Наследование (Inheritance): Механизм, позволяющий одному классу (дочернему или производному) наследовать свойства и методы другого класса (родительского или базового). Это способствует повторному использованию кода и созданию иерархий классов.
- Полиморфизм (Polymorphism): Возможность объектов разных классов реагировать на один и тот же метод по-разному. Это позволяет писать более гибкий и обобщенный код.
Определение классов
Классы в PHP определяются с помощью ключевого слова class, за которым следует имя класса и тело класса, заключенное в фигурные скобки {}.
<?php
class Car {
// Свойства (атрибуты) класса
public $color;
public $model;
// Метод класса
public function startEngine() {
echo "Двигатель заведен!\n";
}
public function setColor($newColor) {
$this->color = $newColor;
}
public function getColor() {
return $this->color;
}
}
?>class Car: Объявление класса с именемCar. Имена классов обычно начинаются с заглавной буквы.public $color;иpublic $model;: Объявление публичных свойств$colorи$model. К публичным свойствам можно обращаться из любого места.public function startEngine() { ... }: Объявление публичного методаstartEngine(). К публичным методам также можно обращаться из любого места.$this: Специальная переменная, которая используется внутри методов класса для обращения к свойствам и методам текущего объекта.
Создание объектов (экземпляров класса)
Для использования класса необходимо создать его объект (экземпляр). Это делается с помощью ключевого слова new.
<?php
$myCar = new Car();
$anotherCar = new Car();
// Обращение к свойствам объекта
$myCar->color = "красный";
$myCar->model = "Toyota";
$anotherCar->color = "синий";
$anotherCar->model = "BMW";
echo "Моя машина: " . $myCar->color . " " . $myCar->model . "\n";
echo "Другая машина: " . $anotherCar->color . " " . $anotherCar->model . "\n";
// Вызов метода объекта
$myCar->startEngine(); // Выведет: Двигатель заведен!
?>Конструктор (__construct)
Конструктор — это специальный метод класса, который автоматически вызывается при создании нового объекта этого класса. Он используется для инициализации свойств объекта. Конструктор определяется с именем __construct().
<?php
class Person {
public $name;
public $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
echo "Создан новый объект Person с именем " . $this->name . ".\n";
}
public function greet() {
echo "Привет, меня зовут " . $this->name . ", и мне " . $this->age . " лет.\n";
}
}
$person1 = new Person("Иван", 30); // Автоматически вызовется __construct
$person2 = new Person("Анна", 25);
$person1->greet();
$person2->greet();
?>Инкапсуляция: Модификаторы доступа
PHP предоставляет модификаторы доступа для управления видимостью свойств и методов класса:
public: Свойства и методы, объявленные какpublic, доступны из любого места (внутри класса, вне класса, в дочерних классах).protected: Свойства и методы, объявленные какprotected, доступны внутри класса, а также в дочерних классах. Они недоступны извне класса.private: Свойства и методы, объявленные какprivate, доступны только внутри класса, в котором они определены. Они недоступны ни извне класса, ни в дочерних классах.
Использование модификаторов доступа помогает реализовать инкапсуляцию, скрывая внутренние детали реализации класса и контролируя доступ к его состоянию.
<?php
class BankAccount {
private $balance;
public $accountNumber;
public function __construct($accountNumber, $initialBalance) {
$this->accountNumber = $accountNumber;
$this->balance = $initialBalance;
}
public function deposit($amount) {
if ($amount > 0) {
$this->balance += $amount;
echo "Внесено " . $amount . ". Текущий баланс: " . $this->getBalance() . "\n";
} else {
echo "Сумма для внесения должна быть положительной.\n";
}
}
public function withdraw($amount) {
if ($amount > 0 && $this->balance >= $amount) {
$this->balance -= $amount;
echo "Снято " . $amount . ". Текущий баланс: " . $this->getBalance() . "\n";
} else {
echo "Недостаточно средств или некорректная сумма.\n";
}
}
private function getBalance() {
return $this->balance;
}
public function checkBalance() {
echo "Баланс счета " . $this->accountNumber . ": " . $this->getBalance() . "\n";
}
}
$account1 = new BankAccount("12345", 1000);
$account1->deposit(500);
$account1->withdraw(200);
$account1->checkBalance();
// $account1->balance = -100; // Ошибка: свойство private
// echo $account1->getBalance(); // Ошибка: метод private
?>Наследование
Наследование позволяет создавать новые классы (дочерние) на основе существующих классов (родительских). Дочерние классы наследуют свойства и методы родительского класса и могут добавлять свои собственные свойства и методы или переопределять (override) унаследованные методы. Наследование реализуется с помощью ключевого слова extends.
<?php
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function makeSound() {
echo "Животное издает звук.\n";
}
}
class Dog extends Animal {
public function makeSound() {
echo "Гав!\n"; // Переопределение метода
}
public function fetch() {
echo $this->name . " приносит палку.\n";
}
}
class Cat extends Animal {
public function makeSound() {
echo "Мяу!\n"; // Переопределение метода
}
public function purr() {
echo $this->name . " мурлычет.\n";
}
}
$animal1 = new Animal("Неизвестное животное");
$dog1 = new Dog("Бобик");
$cat1 = new Cat("Мурка");
$animal1->makeSound(); // Выведет: Животное издает звук.
$dog1->makeSound(); // Выведет: Гав! (переопределенный метод)
$dog1->fetch(); // Выведет: Бобик приносит палку.
$cat1->makeSound(); // Выведет: Мяу! (переопределенный метод)
$cat1->purr(); // Выведет: Мурка мурлычет.
?>Полиморфизм
Полиморфизм означает "много форм". В контексте ООП это означает, что объекты разных классов могут обрабатываться единообразно через общий интерфейс (например, родительский класс или интерфейс).
В примере с наследованием метод makeSound() является полиморфным, так как объекты классов Dog и Cat (унаследованных от Animal) реагируют на этот метод по-разному.
Абстрактные классы и методы
Абстрактный класс — это класс, который не может быть инстанцирован (нельзя создать его объект). Он служит в качестве базового класса для других классов и может содержать абстрактные методы. Абстрактный метод — это метод, объявленный с ключевым словом abstract и не имеющий реализации в абстрактном классе. Дочерние классы, наследующие абстрактный класс, обязаны реализовать все его абстрактные методы.
<?php
abstract class Shape {
abstract public function area();
public function printArea() {
echo "Площадь: " . $this->area() . "\n";
}
}
class Circle extends Shape {
private $radius;
public function __construct($radius) {
$this->radius = $radius;
}
public function area() {
return pi() * $this->radius * $this->radius;
}
}
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
public function area() {
return $this->width * $this->height;
}
}
// $shape = new Shape(); // Ошибка: нельзя создать экземпляр абстрактного класса
$circle = new Circle(5);
$rectangle = new Rectangle(4, 6);
$circle->printArea(); // Выведет: Площадь: 78.539816339745
$rectangle->printArea(); // Выведет: Площадь: 24
?>Интерфейсы
Интерфейс определяет контракт, которому должны следовать классы, реализующие этот интерфейс. Интерфейс объявляет набор методов (без их реализации). Класс может реализовывать несколько интерфейсов. Интерфейсы определяются с помощью ключевого слова interface, а классы реализуют интерфейсы с помощью ключевого слова implements.
<?php
interface Logger {
public function log($message);
}
class FileLogger implements Logger {
private $filename;
public function __construct($filename) {
$this->filename = $filename;
}
public function log($message) {
file_put_contents($this->filename, date('Y-m-d H:i:s') . " - " . $message . "\n", FILE_APPEND);
}
}
class DatabaseLogger implements Logger {
public function log($message) {
echo "Запись в базу данных: " . $message . "\n";
// Здесь будет код для записи в базу данных
}
}
$fileLog = new FileLogger('app.log');
$dbLog = new DatabaseLogger();
$fileLog->log("Приложение запущено.");
$dbLog->log("Пользователь вошел в систему.");
function processLog(Logger $logger, $message) {
$logger->log($message);
}
processLog($fileLog, "Важное событие в файле.");
processLog($dbLog, "Важное событие в базе данных.");
?>Трейты (Traits)
Трейты — это механизм для повторного использования кода в классах, не связанный с наследованием. Трейт похож на класс, но он предназначен для включения в другие классы. Класс может использовать несколько трейтов. Трейты определяются с помощью ключевого слова trait, а классы используют трейты с помощью ключевого слова use.
<?php
trait Loggable {
public function logMessage($message) {
echo date('Y-m-d H:i:s') . " - " . $message . "\n";
}
}
class User {
use Loggable;
public $name;
public function __construct($name) {
$this->name = $name;
$this->logMessage("Создан пользователь: " . $name);
}
public function login() {
$this->logMessage($this->name . " вошел в систему.");
}
}
class Product {
use Loggable;
public $title;
public function __construct($title) {
$this->title = $title;
$this->logMessage("Создан продукт: " . $title);
}
}
$user1 = new User("Алексей");
$user1->login();
$product1 = new Product("Ноутбук");
?>ООП является мощным инструментом для организации и структурирования PHP-кода, особенно для больших и сложных проектов. Понимание основных концепций ООП и умение их применять значительно повышает качество и поддерживаемость вашего кода.