## 對象和數據結構
### 使用 getters 和 setters
在PHP中你可以對方法使用`public`, `protected`, `private` 來控制對象屬性的變更。
* 當你想對對象屬性做獲取之外的操作時,你不需要在代碼中去尋找并修改每一個該屬性訪問方法
* 當有`set`對應的屬性方法時,易于增加參數的驗證
* 封裝內部的表示
* 使用set*和get*時,易于增加日志和錯誤控制
* 繼承當前類時,可以復寫默認的方法功能
* 當對象屬性是從遠端服務器獲取時,`get`、`set`易于使用延遲加載
此外,這樣的方式也符合OOP開發中的[開閉原則](https://segmentfault.com/a/1190000013123183)
**差:**
```php
class BankAccount
{
public $balance = 1000;
}
$bankAccount = new BankAccount();
// Buy shoes...
$bankAccount->balance -= 100;
```
**優:**
```php
class BankAccount
{
private $balance;
public function __construct(int $balance = 1000)
{
$this->balance = $balance;
}
public function withdraw(int $amount): void
{
if ($amount > $this->balance) {
throw new \Exception('Amount greater than available balance.');
}
$this->balance -= $amount;
}
public function deposit(int $amount): void
{
$this->balance += $amount;
}
? ?public function getBalance(): int
{
return $this->balance;
}
}
$bankAccount = new BankAccount();
// Buy shoes...
$bankAccount->withdraw($shoesPrice);
// Get balance
$balance = $bankAccount->getBalance();
```
### 對象屬性多使用private/protected限定
* 對`public`方法和屬性進行修改非常危險,因為外部代碼容易依賴他,而你沒辦法控制。**對之修改影響所有這個類的使用者。
* 對`protected`的修改跟對`public`修改差不多危險,因為他們對子類可用,他倆的唯一區別就是可調用的位置不一樣,**對應修改影響所有使用這個類的地方。
* 對`private`的修改保證了這部分代碼**只會影響當前類。
當需要控制類里的代碼可以被訪問時才用`public/protected`,其他時候都用`private`。
**差:**
```php
class Employee
{
public $name;
public function __construct(string $name)
{
$this->name = $name;
}
}
$employee = new Employee('John Doe');
echo 'Employee name: '.$employee->name; // Employee name: John Doe
```
**優:**
```php
class Employee
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
}
$employee = new Employee('John Doe');
echo 'Employee name: '.$employee->getName(); // Employee name: John Doe
```