Why Encapsulate
Tags: php
Published: 2019-04-19 15:27:07

---
title: Why Encapsulate
published: true
description: simple PHP snippets for those are not used to encapsulation yet
tags: php
cover_image: https://thepracticaldev.s3.amazonaws.com/i/f21nm0m595rtbj2u1m1v.png
---

I'm pretty sure you can find enough material about encapsulation in the context of Object Oriented programming paradigm on the Internet. Thus, my approach here is to expose a simple PHP snippet for those are not used to encapsulation yet.

Let's say you have a `wallet` object and you want to impose some restrictions on its public interface. I mean, you want to guide how client code should use your `wallet` object.

Among other attributes and methods, let's keep our object as simple as we can and stay focused on encapsulation. For this reason, let's start with a `$balance` and a `$limit` attributes, besides two _public_ methods, `withdraw()` and `deposit()`, and a _private_ one, the `setLimit()` method.

```php
class Wallet
{
    /**
     * Balance of the wallet
     *
     * @var float
     */
    private $balance;

    /**
     * Availabe limit for the wallet
     *
     * @var float
     */
    private $limit;

    /**
     * Creates a Wallet with a initial balance and a certain limit.
     * @param  float  $balance
     * @param  float  $limit
     */
    public function __construct(float $balance, float $limit = 0)
    {
        $this->limit = $this->setLimit($limit);

        if ($balance + $this->limit < 0) {
            throw new Exception("Can't create a wallet with balance under limit.");
        }

        $this->balance = $balance;
    }

    private function setLimit(float $limit)
    {
        return $this->limit = abs($limit);
    }

    /**
     * Increase balance
     * @param  float  $amount
     * @return float
     */
    public function deposit(float $amount)
    {
        return $this->balance += $amount;
    }

    /**
     * Decrease balance
     * @param  float $amount
     * @return float
     */
    public function withdraw(float $amount)
    {
        $amount = abs($amount);

        if ($this->balance + $this->limit - $amount < 0) {
            throw new Exception("Insuficient funds.");
        }

        return $this->balance -= $amount;
    }

    /**
     * A string representation for the wallet's balance
     * @return string
     */
    public function __toString()
    {
        return sprintf("Balance: $ %.2f", $this->balance);
    }
}
```

First, we don't want to allow client code to create Wallets with no balance, or with a balance under a certain limit. Thus we've defined this initial rules in the constructor method.

Next, we can't let the client code manipulate the balance of a wallet directly. This change must occur through one of the assessor methods, 'deposit()' or 'withdraw()'. For this reason, we've defined the `$balance` property as private.

We also want to ensure that the balance of a portfolio does not fall below the limit set in the builder. We can define this business rule in the `withdraw()` method.

## Using the Wallet class

With our Wallet class defined, we can easily create a new wallet, specifying its initial balance and limit:

```php
$my_wallet = new Wallet(200, 100);
```

Changes on `$balance` property are limited through `deposit()` and `withdraw()` methods:

```php
$my_wallet->deposit(1450.25);
$my_wallet->withdraw(500.50);
```

We are able to see a nice string representation of a Wallet object just printing it, thanks to the `__toString()` magic method:

```php
print($my_wallet);
```

Lastly, we are verifying for a _limit_ violation when withdrawing or when creating a new Wallet object:

```php
# Will throw an Exception: "Insuficient funds"
$my_wallet->withdraw(2000.00);

# Will throw an Exception: Can't create a wallet with balance under limit.
$other_wallet = new Wallet(-225.15, 150);
```

The main goal of _encapsulation_ is to protect entire object data from being accessible to its clients. Our business rule about the _limit_ is hidden from client code. We have blundled the data with the methods that operate on that data.