Exemplo interativo de programação orientada a objetos e princípios de design

Brinque com o código online aqui: http://codepad.viper-7.com/PWuLrw

<?php

class Tram {
protected $passengers = array();
// Passenger in the parameters means only allow Passengers

public function enterPassenger( Passenger $onePassenger ) {
// since I'm coding an interface I known 100% that the enterTram method exists
// now trying commenting out line 22 and 27-29 and run the code again
$onePassenger
->enteredTram();

$this
->passengers[] = $onePassenger;
}

public function getAllPassengers() {
return $this->passengers;
}
}

interface IPassenger {
// interfaces force minimum required methods and parameters
public function enteredTram();
}

abstract class Passenger implements IPassenger {
// comment out this method and see what happens
public function enteredTram(){
echo
"passenger entered tram <br />n";
}

public function getColor(){
echo
"sorry I don't know my color yet <br />n";
}
}

// a human IS A special kind of Passenger
class Human extends Passenger {
public function fart(){
echo
"this Human farted <br />n";
}
}

// a bird IS A special kind of Passenger
class Bird extends Passenger {
protected $color = 'bright red';

public function tweet(){
echo
"this bird went, tweet tweet <br />n";
}

// I used "encapsulation" by exposing the "value" of the protected $color property, but not the property itself
// since it's set to "protected". I'm also following the open / closed principle by hiding (closing) the internal
// parts of this class, but allowing new classes to extend from this one. This prevents bad things from happening
// in the future. Lets say you wanted to check if the bird was dead BEFORE you told them the color. Maybe it WAS
// bright red, but now it's a dull red. You could do that check if you didn't expose the $color property. Nobody
// (your instantiated objects) knowns that $color exists. They only know that getColor() will get them a color. So
// that means getColor() worked BEFORE you added the code to check if the bird was dead AND after you added that
// check, so you didn't break the "contract" with the instantiated objects (normally referred as client code)
public function getColor(){
echo
"this bird is {$this->color} <br />n";
}
}

$human1
= new Human();

var_dump
( 'is this human a Passenger?', $human1 instanceof Passenger );

$bird1
= new Bird();

var_dump
( 'is this bird a Passenger too?', $bird1 instanceof Passenger );

$human1
->fart();
$bird1
->tweet();

$human1
->getColor();
$bird1
->getColor();

// lets try to instantiate a "passenger"
$passenger
= new Passenger();

// oh crap, fatal error, you can't make (instantiate) individual passengers directly with an abstract class, make
// another class instead that DEFINES a specific kind of Passenger

// comment out line 79

// now lets enter the passengers into the tram
$tram
= new Tram();

$tram
->enterPassenger( $human1 );
$tram
->enterPassenger( $bird1 );
$tram
->enterPassenger( "Alien" );
// oh crap strings of Aliens aren't allowed into the tram, only Passenger(s) are allowed

var_dump
( $tram->getAllPassengers() );

Aprenda a construir um ambiente de desenvolvimento local com um servidor Linux e PHP 5.6 em menos de 10 minutos. Vou mostrar como fazer isso: http://www.airpair.com/vagrant/workshops/emulate-staging-servers-with-vagrant .