Friday, January 30, 2015

Making our classes self-contained with encapsulation

Most of the classes we creates contained public properties, and outside code has been able to reach into a class's innards and manipulate its public properties at will. Usually, this is a bad idea. One of the strengths of OOP is the concept of encapsulation. This means that a class's internal data should be protected from being directly manipulated from outside, and that the details of the class's implementation — such as how it stores values or manipulates data — should be hidden from the outside world. By doing this, we gain two advantages:

We can change our class's implementation details at any time without affecting code that uses the class

We can trust the state of an object to be valid and to make sense

Generally speaking, all internal properties of a class should be declared private. If outside code needs to access those variables, it should be done through a public method. This gives our class the opportunity to validate the changes requested by the outside code and accept or reject them.

For example, if we are building a banking application that handles details of customer accounts,  we might have an Account object with a property called $totalBalance and methods called makeDeposit() and makeWithdrawal(). The only way to affect the balance should be to make a withdrawal or a deposit. If the $totalBalance property is implemented as a public property, we could write outside code that would increase the value of that variable without having to actually make a deposit. Obviously, this would be bad for the bank.

Instead, we implement this property as a private property and provide a public method called getTotalBalance(), which returns the value of that private property:

class Account
 {
   private $_totalBalance = 0;

   public function makeDeposit( $amount )
 {
     $this->_totalBalance += $amount;
   }

   public function makeWithdrawal( $amount )
 {
     if ( $amount < $this->_totalBalance )
 {
       $this->_totalBalance -= $amount;
     }
 else
 {
       die( "Insufficient funds<br />" );
     }
   }

   public function getTotalBalance()
 {
     return $this->_totalBalance;
   }
 }

 $a = new Account;
 $a->makeDeposit( 500 );
 $a->makeWithdrawal( 100 );
 echo $a->getTotalBalance() . "<br />";  // Displays "400";
 $a->makeWithdrawal( 1000 );  // Displays "Insufficient funds"

Because the variable storing the account balance is private, it can't be manipulated directly. Customers have to actually make a deposit via makeDeposit() if they want to increase the value of their account.

By encapsulating internal data and method implementations, an object-oriented application can protect and control access to its data and hide the details of implementation, making the application more flexible and more stable.

No comments:

Post a Comment