OOP real world scenario:
Imagine you have a class Vehicles and they have (protected) wheels. You have different Vehicles with wheels, but to addWheel to a Bike, is different from addWheel to an Aircraft.
Code advantage:
Using getter and setter, you can use typehinting.
Compare those snippets:
class Car {
public $wheels;
}
$bmw = new Car;
$bmw->wheels = 'piece of paper';
The above code let's you add anything as a wheel, but can you use a piece of paper as a wheel?
Now with getter and setter:
class Car {
protected wheels;
public function __construct() {
$this->wheels = new ArrayIterator;
}
public function addWheel(Wheel $wheel) {
$this->wheels->add($wheel);
return $this;
}
public function removeWheel(Wheel $wheel) {
$this->wheels->remove($wheel);
return $this;
}
}
class Wheel {
}
$bmw = new Car;
$bmw->addWheel('piece of paper'); // <-- throws an error!
// paper cannot be used as a wheel
$bmw->addWheel(new Wheel); // <-- good :-)
More code, to be more straightforward. Imagine you have RearWheels and FrontWheels:
class Wheel {
}
class FrontWheel extends Wheel {
}
class RearWheel extends Wheel {
}
class Car {
protected wheels;
public function __construct() {
$this->wheels = new ArrayIterator;
}
public function addWheel(Wheel $wheel) {
// check for already existing Wheels here.
// Pseudo Code:
if (wheels typeof RearWheel > 2) {
throw new Exception('cannot add more than 2 RearWheels to the Car');
}
return $this;
}
public function removeWheel(Wheel $wheel) {
$this->wheels->remove($wheel);
return $this;
}
}