Last Updated: February 25, 2016
·
2.158K
· 2upmedia

Interactive example of Object Oriented Programming and Design Principles

Play with the code online here: 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() );

Take it up a notch: Learn how to build local development environment with a linux server and PHP 5.6 in under 10 minutes. I'll be showing how to do this: http://www.airpair.com/vagrant/workshops/emulate-staging-servers-with-vagrant.