Ответ 1
В двух словах, класс является планом для объекта. И объект инкапсулирует концептуально связанное состояние и ответственность чего-то в вашем приложении и обычно предлагает интерфейс программирования, с которым можно взаимодействовать с ними. Это способствует повторному использованию кода и повышает ремонтопригодность.
Представьте замок:
namespace MyExample;
class Lock
{
private $isLocked = false;
public function unlock()
{
$this->isLocked = false;
echo 'You unlocked the Lock';
}
public function lock()
{
$this->isLocked = true;
echo 'You locked the Lock';
}
public function isLocked()
{
return $this->isLocked;
}
}
Игнорируйте объявление namespace
, private
и public
прямо сейчас.
Класс Lock - это план всех блокировок в вашем приложении. Блокировка может быть заблокирована или разблокирована, что представлено свойством $isLocked
. Поскольку он может иметь только эти два состояния, я использую логическое значение (true
или false
), чтобы указать, какое состояние применяется. Я могу взаимодействовать с Lock через его методы lock
и unlock
, которые соответственно изменят состояние. Метод isLocked
даст мне текущее состояние блокировки. Теперь, когда вы создаете объект (также часто называемый экземпляром) из этого плана, он будет инкапсулировать уникальное состояние, например.
$aLock = new Lock; // Create object from the class blueprint
$aLock->unlock(); // You unlocked the Lock
$aLock->lock(); // You locked the Lock
Позвольте создать еще один замок, также инкапсулируя его собственное состояние
$anotherLock = new Lock;
$anotherLock->unlock(); // You unlocked the Lock
но поскольку каждый объект/экземпляр инкапсулирует его собственное состояние, первая блокировка остается заблокированной
var_dump( $aLock->isLocked() ); // gives Boolean true
var_dump( $anotherLock->isLocked() ); // gives Boolean false
Теперь вся ответственность за блокировку блокировки или разблокировку блокируется в классе Lock. Вам не нужно перестраивать его каждый раз, когда вы хотите что-то заблокировать, и если вы хотите изменить способ работы Lock, вы можете изменить это в проекте Lock, а не на всех классах, имеющих блокировку, например. Дверь:
class Door
{
private $lock;
private $connectsTo;
public function __construct(Lock $lock)
{
$this->lock = $lock;
$this->connectsTo = 'bedroom';
}
public function open()
{
if($this->lock->isLocked()) {
echo 'Cannot open Door. It is locked.';
} else {
echo 'You opened the Door connecting to: ', $this->connectsTo;
}
}
}
Теперь, когда вы создаете объект Door, вы можете назначить ему объект Lock. Поскольку объект Lock обрабатывает всю ответственность за то, что что-то заблокировано или разблокировано, двери не нужно заботиться об этом. Фактически, любые объекты, которые могут использовать Lock, не должны заботиться, например, Chest
class Chest
{
private $lock;
private $loot;
public function __construct(Lock $lock)
{
$this->lock = $lock;
$this->loot = 'Tons of Pieces of Eight';
}
public function getLoot()
{
if($this->lock->isLocked()) {
echo 'Cannot get Loot. The chest is locked.';
} else {
echo 'You looted the chest and got:', $this->loot;
}
}
}
Как вы можете видеть, непобедимость сундука отличается от репутации двери. Сундук содержит добычу, а дверь отделяет комнаты. Вы можете закодировать заблокированное или разблокированное состояние в обоих классах, но с отдельным классом Lock вам не нужно и может повторно использовать блокировку.
$doorLock = new Lock;
$myDoor = new Door($doorLock);
$chestLock = new Lock;
$myChest new Chest($chestLock);
У сундуков и дверей теперь есть свои уникальные замки. Если замок был магическим замком, который может существовать одновременно в нескольких местах, например, в квантовой физике, вы можете назначить один и тот же замок как сундуку, так и двери, например.
$quantumLock = new Lock;
$myDoor = new Door($quantumLock);
$myChest new Chest($quantumLock);
и когда вы unlock()
$quantumLock
, обе двери и сундук будут разблокированы.
Хотя я допускаю, что квантовые блокировки являются плохим примером, он иллюстрирует концепцию совместного использования объектов вместо того, чтобы восстанавливать состояние и ответственность повсюду. Примером реального мира может быть объект базы данных, который вы передаете классам с использованием базы данных.
Обратите внимание, что приведенные выше примеры не показывают, как добраться до блокировки сундука или двери, чтобы использовать методы lock()
и unlock()
. Я оставляю это как упражнение для вашей работы (или кого-то еще для добавления).
Также проверьте Когда использовать self over $this? для более подробного объяснения классов и объектов и того, как с ними работать
Для некоторых дополнительных ресурсов проверьте