Registreren

    Informatie

    Het is heel gemakkelijk om lid te worden. Door je gegevens op te geven op de registratie pagina ontvang je automatisch een email met je inlog gegevens.

  • Registreer je hier

Aanmelden

    Informatie

    Omdat je niet aangemeld bent is het gebruikerspaneel niet beschikbaar. Vul hiernaast je gegevens in om gebruik te maken van het gebruikerspaneel.

Aanmeldformulier


OOP in PHP

PHP is een scripttaal, die bedoeld is om op webservers dynamische webpagina's te creëren. PHP is in 1994 ontworpen door Rasmus Lerdorf, een senior software engineer bij IBM. Destijds was de taal duidelijk geïnspireerd door Perl.

Aanvankelijk stonden de letters PHP voor Personal Home Page (de volledige naam was Personal Home Page/Forms Interpreter, PHP/FI). Sinds PHP 3.0 is de betekenis een recursief acroniem geworden: PHP: Hypertext Preprocessor.

OOP in PHP

Berichtdoor RedRose » 03 Sep 2008 21:22

Inleiding
Ik ben zelf een groot voorstander van objectgeoriënteerd programmeren. Voor mij is het een geweldige manier om mijn code logisch en herbruikbaar te maken.

Sinds PHP5 zijn de mogelijkheden wat betreft OOP (object oriented programming) binnen PHP enorm gegroeid - het is nu niet alleen mogelijk om bepaalde klassen aan te maken, maar ook om gebruik te maken van abstractie, interfaces, access modifiers en nog veel meer.

In dit artikel zal ik een kort overzicht geven van de mogelijkheden van OOP. Dit artikel kan gelezen worden als een introductie in OOP, hoewel de voorbeelden vooral zijn toegespitst op de toepassing van OOP binnen PHP.


Objecten
Alles is een object: de computer, de klok aan de muur, de kat op de vensterbank en jij zelf. Kenmerken van een object zijn dat ze een toestand (state) en gedrag (behavior) hebben. Bij het programmeren schrijven we geen objecten; maar klassen. Klassen zijn definities van objecten. Ze zijn als het ware de taartvorm om een taart te maken.


Methoden en velden
Binnen klasses zijn methoden en klassen aan te wijzen. Methoden zijn functies binnen een klasse, ze werken ook op dezelfde manier als normale functies. Velden zijn variabelen binnen een klasse.


Een eenvoudige klasse
De volgende klasse geeft een lade weer. De lade kan - zoals de meeste laden - open en dicht.

PHP
Code: Alles selecteren
class Drawer
{
   // Status for this drawer:
   // true = open, false = closed
   private $status = false;
 
   
/**
    * Set the status for this drawer.
    * @param $status The status for the drawer
    */
   public function setStatus( $status )
   {
      $this->status = $status;
   }
 
   
/**
    * Get the status for this drawer.
    */
   public function getStatus()
   {
      return $this->status;
   }
}
 
$drawer 
= new Drawer(); // Construct a drawer.
$drawer->setStatus( true ); // Open the drawer.
var_dump( $drawer->getStatus(); ) // Will return true.     

Allereerst schrijven we de klasse Drawer, met het veld status en de methods SetStatus en GetStatus.

Vervolgens wijzen we een instantie van de klasse toe aan $drawer, waarna we op die instantie de verschillende methods aanroepen, met behulp van de operator ->. Deze operator geeft aan dat je wilt werken met een methode of een veld van een klasse.


Constructors
Vaak is het de bedoeling dat een klasse met bepaalde waarden geïnitialiseerd worden. Hiervoor zijn zogenaamde constructors in het leven geroepen. Constructors zijn implementaties van de public function __construct (let op: dit is een gereserveerde naam, en mag dus niet voor andere functies gebruikt worden!). Als we in het bovenstaande voorbeeld een beginstatus willen toevoegen, kan dat op de volgende manier. Uitleg zal ik achterwege laten – de code op zich zou duidelijk genoeg moeten zijn.

PHP
Code: Alles selecteren
class Drawer
{
   // Status for this drawer:
   // true = open, false = closed
   private $status = false;
 
   
/**
    * Create the Drawer.
    * @param $initialstatus The initial status.
    */
   public function __construct( $initialstatus )
   {
      $this->status = $initialstatus;
   }
   
   
/**
    * Set the status for this drawer.
    * @param $status The status for the drawer
    */
   public function setStatus( $status )
   {
      $this->status = $status;
   }
 
   
/**
    * Get the status for this drawer.
    */
   public function getStatus()
   {
      return $this->status;
   }
}
 
$drawer 
= new Drawer( false ); // Construct a drawer.
var_dump( $drawer->getStatus() ); // Will return false.
$drawer->setStatus( true ); // Open the drawer.
var_dump( $drawer->getStatus() ); // Will return true.      


Destructors
Iets wat je aan kunt maken moet je natuurlijk ook kunnen slopen, en daarvoor is de methode __destruct (ook weer een gereserveerde naam) in het leven geroepen. Deze methode wordt bij het beëindigen van het script automatisch aangeroepen, maar je kunt hem natuurlijk ook zelf aanroepen.

PHP
Code: Alles selecteren
class DestructableClass
{
   public function __construct()
   {
      echo "Constructing...<br />";
   }
   
   public function __destruct
()
   {
      echo "Destroying...<br />";
   }
}
 
$destructableclass 
= new DestructableClass(); 


Access modifiers
Aan de declaratie van die variabelen en methoden valt ons iets op: de sleutelwoorden private en public. Dit zijn zogenaamde access modifiers: sleutelwoorden die iets zeggen over de mate van toegang tot de velden of methoden. PHP kent drie verschillende access modifiers:

  • public
    Wil zeggen dat dit veld of deze methode beschikbaar is voor een aanroep van buiten de eigen klasse. Je kunt zo een methode dus aanroepen vanuit de rest van de code.
  • private
    Wil zeggen dat dit veld of deze methode slechts beschikbaar is voor de eigen klasse. Aanroepen van buiten zijn dus niet toegestaan.
  • protected
    Wil zeggen dat dit veld of deze methode slechts beschikbaar is voor de eigen klasse en subklassen daarvan.

Encapsulatie
Encapsulatie is een eerste stap op weg naar een objectgeoriënteerde applicatie. Een synoniem voor encapsulatie is inkapseling. Binnen de context van dit artikel houdt het in dat je bepaalde variabelen in een klasse inkapselt, en met bepaalde functies de toegang tot die klas regelt. Behalve dat dit vanuit het oogpunt van veiligheid positief is, vind ik ook de manier van coding mooier dan wanneer er vanuit aanroepende code direct naar de velden binnen de klasse wordt verwezen.

Vaak wil je invloed uitoefenen op de toewijzing van waarden aan je variabelen; bijvoorbeeld omdat alleen de klasse zelf een bepaalde waarde mag veranderen, terwijl de gebruiker wel de mogelijkheid moet hebben om de waarde van die variabele op te vragen. Het is dan mogelijk de variabele private te declareren en door middel van een public methode getValue() de waarde van die variabele te retourneren.

Een voorbeeld van encapsulatie staat bijvoorbeeld al in het eerste codevoorbeeld van dit artikel.


Overerving
Klassen kunnen elkaar uitbreiden. Een nieuwe klasse bouwt dan voort op een andere. Hierdoor kan een OOP-ontwerp heel logisch in elkaar zitten.

Het overerven moet je op de volgende manier zien: je hebt de klasse Car. In deze klasse heb je bijvoorbeeld een method forward en een veld wielbasis gezet. Nu schrijven we een klasse Mercedes. Een Mercedes breidt als het ware de klasse Car uit. Als je nu ook een klasse PCHooftTractor -olijke knipoog- aanmaakt, krijgt die bijvoorbeeld een veel bredere wielbasis dan de Mercedes. Op deze wijze heb je jezelf voor de klassen Mercedes en PCHooftTractor een heleboel typwerk bespaard: het is immers niet meer noodzakelijk beide klassen een eigen methode forward te geven.

Overigens is het ook mogelijk door de childklasse geërfde methoden te overschrijven. Dit is bijvoorbeeld handig wanneer men de functie openTrunk opneemt in de klasse Car. Sommige auto's openen de kofferbak aan voorkant, hoewel je dit niet zo vaak ziet.

PHP
Code: Alles selecteren
class BaseClass
{
   public function baseFunction()
   {
      echo "baseFunction()<br />";
   }
}
 
class ChildClass extends BaseClass
{
   public function __construct()
   {
      $this->baseFunction();
   }
}
 
new ChildClass
(); 


Interfacing
In het dagelijks leven is een interface een manier van communicatie tussen twee systemen, bijvoorbeeld de afstandsbediening die je de mogelijkheid biedt met de televisie (of de geluidsinstallatie, de thermostaat, het koffiezetapparaat...) te communiceren, maar ook een taal is een interface.

Ook in de programmeerwereld is het mogelijk interfaces te schrijven. Interfaces zijn een soort blauwdruk van de klasse, die definities van methoden bevatten. Wanneer een klasse een interface implementeert belooft hij alle methoden te zullen implementeren.

Dat dit handig is blijkt bijvoorbeeld binnen rallies met een navigator. Zowel coureur als navigator zijn gebaat aan een gestroomlijnde conversatie. Zouden zij echter maar zeggen wat ze op dat moment geschikt lijkt, dan krijg je op een gegeven moment de volgende conversatie: "Ga die ene kant op!" ... "Nee, die andere kant, oetlul!" en er zou weer een auto uit de race zijn. Daarom hebben navigator en coureur bepaalde woorden afgesproken: links, rechts, enzovoort.

PHP
Code: Alles selecteren
interface IFace
{
   public function callback( $var );
}
 
class Implementation implements IFace
{
   private $user;
   
   public function __construct
()
   {
      $this->user = new InterfaceUser( $this );
   }
   
   public function callback
( $var )
   {
      print( $var );
   }
}
 
class InterfaceUser
{
   public function __construct( Implementation $impl )
   {
      $impl->callback( 'blaat' );
   }
}
 
new Implementation
(); 

In dit voorbeeld is callback( $var ) een door de interface afgedwongen functie, waaraan elke implementatie zijn eigen invulling kan geven, waardoor je vanuit andere klassen of andere code er vanuit kunt gaan dat die functie aanwezig is.


Abstracte klassen
Een andere mogelijkheid is het gebruik van abstracte klassen. In een abstracte klassen kun je nalaten (een deel van) de methoden te implementeren. In een subklasse van deze abstracte klasse implementeer je die methoden vervolgens wel weer.

Het gebruik van interfaces en abstracte klassen is bijvoorbeeld handig bij het abstraheren van een databasesysteem. Hiervoor is een (abstracte) parentklasse Database nodig, die door allerlei childklassen (Database_MySQL, Database_PostgreSQL, Database_MSAccess, ...) geëxtend worden. De parentklasse fungeert hier duidelijk als een blauwdruk.

PHP
Code: Alles selecteren
abstract class AbstractClass
{
   protected function getPrefix()
   {
      return 'PREFIX_';
   }
   
   public abstract function callback
( $var );
}
 
class Implementation extends AbstractClass
{
   private $user;
   
   public function __construct
()
   {
      $this->user = new AbstractUser( $this );
   }
   
   public function callback
( $var )
   {
      print( $this->GetPrefix().$var );
   }
}
 
class AbstractUserUser
{
   public function __construct( Implementation $impl )
   {
      $impl->callback( 'blaat' );
   }
}
 
new Implementation
(); 


Modularisatie
OOP maakt het de programmeur gemakkelijk modularisatie toe te passen. Zo is het heel gemakkelijk om een algemene (abstracte!) paginaklasse te schrijven met de basisfunctionaliteit voor elke pagina (denk bijvoorbeeld aan variabelenbeheer) en voor elke pagina die je maakt een klasse te schrijven die erft van de paginaklasse. Op deze wijze is het heel eenvoudig extra pagina's toe te voegen die een bepaalde functionaliteit toevoegen. Zeker in combinatie met aparte klassen voor de database, output, enzovoort is dit een zeer krachtig concept.


Naamgeving
Het is prettig een bepaalde consequentie in de naamgeving te handhaven. Zo schrijf ik namen van methoden over het algemeen met een kleine letter, terwijl ik namen van klassen laat beginnen met hoofdletters. Bovenstaande schrijfwijze is een redelijk gangbare wijze; ik kom het zeer vaak - vaker dan andere wijzen - tegen, hoewel het in de C-wereld gebruikelijker is functienamen met een hoofdletter te beginnen.

Belangrijker dan de schrijfwijze is het om de methoden handige, herkenbare namen te geven. Als je in je klasse een methode a() hebt staan, moet je eerst aan de slag om uit te zoeken wat a() doet. Natuurlijk kun je ook commentaar schrijven bij elke functie die je schrijft, maar als je duizend maal dezelfde functie aanroept heb je waarschijnlijk geen zin om duizendmaal hetzelfde commentaar daarbij te zetten.
RedRose
Globale moderator
 
Berichten: 1994
Geregistreerd: 14 Jun 2005 18:12

Terug naar PHP



Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 1 gast


cron