OOP PHP


Inspiration och fria översättningar från ”PHP Object Oriented Solutions” av David Powers.

I början av 60 talet började man inse att det var ohållbart att försöka uppdatera, felsöka och utveckla stora och komplexa applikationer med procedural/sekventiell kod som exekveras rad efter rad då detta var väldigt tidsödande och svårt.

Lösningen var att flytta funktionerna bort från huvudscriptet, och sedan klumpa ihop sammanhörande funktioner i logiska enheter som representerade en större och mer allmän ”kugghjul” i applikationen, dessa block kom att kallas för klasser och innehåller oftast metoder (funktioner i klasser kallas för metoder) och medlemsvariabler (även kallade egenskaper, attribut eller fält, i fortsättningen egenskaper) som används för att modifiera ett state av ett objekt (som är en instans av en klass).

Man skulle kunna göra jämförelsen med assemblerprogrammering och högnivåspråk, där den senare har en högre abstraktionsnivå och detsamma gäller med förhållandet mellan procedural kod och att arbeta med klasser och tillhörande metoder där en klass fungerar som en fabrik och varje metod är en avdelning som utför en specifik uppgift.

Så varför är det så bra med OOP sättet att programmera? Jo, genom att skapa så generiska moduler som möjligt får man fram script som är återanvändningsbar och så klart blir det mycket lättare att underhålla scripten.

Skydda dataintegritet » inkapsling

Inkapsling betyder att man ser till att varje enskild del av applikationen är avskilt från varandra och på det sättet inte kan störa (förutom genom angivna metoder). På detta sätt undviker man dominoeffekten som uppstår vid close coupling, så man bör eftersträva loose coupling. Man anger synlighet för egenskaper med tre olika nyckelord: public, private och protected, public är synlig från andra cript innanför och utanför klassen, protected och private o andra sidan är inte synliga utanför klassen och kan därför inte modifieras godtyckligt. Man kan även ange dessa nyckelord för metoders synlighet, på detta sätt och genom välplanerad struktur skyddar man viktiga egenskaper och funktioner i en applikation.

Exempel på public, private och protected egenskaper:

 

Polymorfism

Betyder egentligen bara att man får använda samma namn på liknande metoder och egenskaper (i kombination med inkapsling). För att illustrera polymorfismens funktionalitet kan vi ta ett exempel; ett människohuvud har en helt annan form än ett fågelhuvud, men dom har båda ungefär samma funktioner d.v.s. äta, andas, prata, se och så vidare, och därför är det vettigt att använda samma namn på båda. OOP PHP tillämpar detta till programmering genom att låta dig ge samma namn till metoder och egenskaper som spelar liknande roller i olika klasser.

Varje klass och objekt är oberoende, så dess metod- och egenskapsnamn är nära förknippade med klassen och alla objekt som skapats från den. Därför finns ingen risk för konflikter, så när en metod eller egenskap används på liknande sätt i olika klasser, är det vettigt att använda samma namn på dom.

Utöka klasser genom arv

När hjulet har uppfunnits, finns det ingen anledning att återuppfinna det – men man kan förbättra det, eller anpassa den för specialiserade användningsområden, så det finns ingen anledning att koda allt från grunden; man kan basera en ny klass på en befintlig.

Precis som du har ärvt vissa egenskaper från dina föräldrar, och utvecklat nya som tillhör dig, kan ett barn klass eller subklass i OOP ärva alla funktioner i sin moderklass (eller superklass), anpassa vissa av dem, och lägga till nya av sina egna.

Man kan utöka alla klasser, inbyggda, tredjepart eller egna men inte klasser som är deklarerade som final.

Underklassen ärver automatiskt alla egenskaper och metoder från sin superklassen, vilket kan vara en stor tidsbesparing om superklassen innehåller en hel del komplex kod. Du kan inte bara lägga till nya metoder och egenskaper, utan du kan också ”skriva över” befintliga metoder och egenskaper (detta är polymorfism i praktiken), anpassa dem till behoven hos den nya klassen.

Så hur ska man välja vad man utökar och vad man bygger från grunden? Jo, precis som det är tänkt med OOP så skapar man generiska klasser från grunden och utökar funktionaliteten för mer specifika klasser.

Loose Coupling

Loose coupling syftar ju som tidigare sagt till tekniken att skapa kod som inte är beroende av annan kod i applikationen genom att ange klara och individuella uppgifter till klasser och därmed inte kan störa andra delar av appen (förutom genom strikt angivna regler).

Loose coupling tekniken går ut på att så långt som mjöligt undvika utveckling för ett specifikt projekt, men det blir i slutändan oundvikligt att skriva metoder som riktar sig till specifika områden och kommer inte att kunna användas i andra applikationer. Tänk så här; när du skapar en klass, fråga dig själv om tekniken skulle kunna användas i andra projekt, om det kan så bör du göra klassen loose coupled d.v.s. så generisk som möjligt.

Design mönster

Många av dom problem som du ska lösa har andra utvecklare garanterat stött på tidigare. Om du hittar ett beprövat sätt att ta hand om ett problem så bör man ta efter lösningen.  Denna typ av kunskap har fått ett namn; design mönster. Ett design mönster är dock inte ett kodblock utan beskriver ett sätt att hantera ett problem.

Utvecklingen av OOP i PHP

Som sagt är PHP ingen OOP språk utan har OOP lösningar. Man började införa OOP i PHP version 3 men det fattades många essentiella funktioner där det största problemet var hur PHP hanterade variabler. Tyvärr fixades inte dom problemen under version 4 eftersom fokus låg på bakåtkompatibilitet.

Tillägget för OOP stöd var oväntad populär, men att fixa tidigarenämnda problemen skulle innebära att att existerande script skulle ”gå sönder”, men när PHP 5 släpptes Juli 2004 gjorde man detta ändå och det blev en radikal förändring av språket.

PHP: s hantering av föremål blev helt omskriven i PHP 5 för att förbättra prestanda och uppfylla kraven i standarder som är gemensamma för andra OOP språk. Den största förändringen från PHP 3 och 4 är det sätt objekt och deras egenskaper hanteras. Ta exemplet nedan:

I PHP 3 och 4, skapar detta en kopia av $objectA och lagrar det som $objectB. Båda objekten agerar därefter oberoende av varandra; ändringar som gjorts i $objectA påverkar inte $objectB, och vice versa. Detta är känt som kopiering av värde och är sättet som PHP normalt hanterar variabler.

Men med PHP 5, istället för att göra en kopia av $objectA, lagras en referens till $objectA i $objectB. Båda variablerna refererar då till samma objekt; ändringar som görs i den ena påverka den andra. Detta är känt som kopiering genom referens. Sedan PHP 5, måste man, för att göra en kopia av ett föremål, använda nyckelordet clone:

clone används endast med objekt (instanser av klasser), medan alla andra variabler fungerar på samma sätt som i PHP 4, det vill säga att man anger ett värde med tilldelnings operatorn för att skapa en kopia.

Andra viktiga skillnader i PHP5:

  • Synlighetsmodifierare som används för att styra åtkomst till egenskaper och metoder (Viktiga för inkapsling)
  • En enhetlig konstruktor namn,  __construct() istället för en metod med samma namn som klassen.
  • Stöd för explicit sanering av resurser genom en destructor funktion __destruct()
  • Stöd för gränssnitt (interface) och abstrakta klasser
  • final klasser
  • Statiska (static) egenskaper och metoder
  • Automatisk laddning av klasser

Utvecklingen av PHP 6 var under utveckling under en lång tid, och ursprungligen var det beräknat att komma ut i början av 2007, men som det ser ut nu kommer ingen version 6 över huvudtaget, utan man hoppar till 7 direkt (som man började jobba på 2014) mest p.g.a. att man vill slippa förvirringen kring gamla referenser till PHP 6, i böcker och artiklar.

Projektet PHP 6 övergavs officiellt Mars 2010 †

Artiklar om frågan PHP 6 / PHP 7;

 

 

Teckenkodning i PHP

Strängar som har tecken med accenter kan orsaka problem p.g.a. olika teckenkodningar, och detta i PHP speciellt.

Ta följande exempelkod som skriver ut En god dag, Världen!” i åtta olika språk:

 

Exempel på fel som uppstår vid teckenkodnings problem i PHP.

Figur 1-1 Exempel på fel som uppstår vid teckenkodnings problem.

Om man använder tecken med accenter kan detta skapa problem vid utskrift. Den allra vanligaste teckenkodningen på webben idag är UTF-8 som är satt som webbstandard av W3C, eftersom den har stöd för så gott som samtliga tecken. Om vi ändrar charset till UTF-8 med hjälp av en content-type header så försvinner problemet.

Lägg till följande kod precis efter start-taggen;

Content-type header charset UTF-8

Figur 1-2 Efter att ha ändrat charset till UTF-8, med content-type header.

 

Om du skulle få problem med utskriften, kan du fixa det genom att lägga till en Content-type header i början av filen (eller ännu hellre i en initierigs-fil som sköter det nödvändiga inställningarna och laddningarna av resurser för att applikationen ska fungera som den ska), som då talar om vilken teckenkodning du vill använda.

En mycket bra artikel om teckenkodning, som jag tycker att du bör läsa;

Strängar är aningen speciella i PHP, och vill du läsa mer om Strängar hittar du allt om dom i dokumentationen, och då speciellt avsnittet ”Details of the String Type”;

…här är en liten, fritt översatt urdrag från den;

”Med tanke på att PHP inte har en specifik teckenkodning för strängar, kan man undra hur stränglitteraler är kodade…  [ ]  …Svaret är att strängar kodas på det sätt som dom kodades i skriptfilen. Således, om skriptet är skrivet i ISO-8859-1,  kommer strängen att kodas i ISO-8859-1 och så vidare.”

 

Gör skillnad på stora & små

Även om PHP inte ser någon skillnad på små och stora bokstäver i funktions- och klassnamn, ska du alltid tänka som att den gör det, eftersom det finns planer på att göra dem skiftlägeskänsliga på samma sätt som variabler.

Bygga klasser

Okej då var det dags att fortsätta med att bygga en klass. Vi börjar med en enkel exempel-klass som mest innehåller kommentarer som förklarar allt:

Som du såg måste en medlemsvariabel föregås av ett synlighets nyckelord; public, protected eller private och om man använder protected eller private ska man ha understreck efter dollartecknet $_  följt av namnet, vilket hjälper utvecklaren att enkelt se vilken synlighet den har.

Så, vad ska man välja? Metoder fungerar ju som klassens reglage, och behöver därför oftast vara public, medan medlemsvariabler bör skyddas med protected eller private så att man inte kommer åt dom oavsiktligt. För att modifiera egenskaper använder man sig av getter och setter metoder.

Exempel på setter och getter metoder:

För att använda en klass i ett script  måste man inkludera det, och likt funktioner kan klasser bara definieras en gång i ett script så det är vettigt att använda någon av; include_once och require_once metoderna för att bara ladda in den en gång i scriptet och undvika en ”Fatal error”.

För att använda en klass behöver man som sagt inkludera det, och sedan skapa en instans av den med hjälp av nyckelordet new;

 

 

protected & private metoder

Det finns lägen då man inte vill att en viss metod ska vara tillgänglig utanför klassen (vilket man också ska eftersträva för att uppnå inkapsling, och med det avskilda delar), då begränsar man dess synlighet med nyckelordet; private eller protected:

Nu kan vi skapa en ny objekt och ange värden för båda medlemsvariablerna, eller lämna ut det:

 

Vad vi har gått igenom hittils:

  • Det man kan göra med objekt står metoderna för och det man lagrar görs i egenskaper.
  • Alla egenskaper måste deklareras med, och föregås av en synlighetsnyckelord; public, protected eller private (detta gäller inte static medlemsvariabler som vi går igenom senare).
  • Att använda synlighetsnyckelord är valfritt när man definierar en metod, men det är rekommenderat att använda ett. Om inget anges, kommer metoden att ses som public.
  • Metod är ett ord för en funktion inne i en klass.
  • Man måste inkludera klassfilen för att kunna använda den. Man bör använda include_once eller require_once för att undvika att omdefiniera klassen, vilket utlöser en ”Fatal error”.
  • Skapa en instans av en klass, d.v.s. ett objekt med nyckelordet new.
  • $this variabeln; när den används i en klass, refererar till nuvarande objekt.
  • Använd -> operatorn för att komma åt en objekts metoder eller medlemsvariabler.
  • Om man försöker använda protected eller private medlemsvariabler från ett script utanför klassen, kommer scriptet att utlösa en ”Fatal error”.
  • Använd getter och setter metoder för att komma åt protected och private medlemsvariabler och metoder.

private – kan endast nås INIFRÅN klassen.

protected – kan nås från INOM klassen och av ÄRVDA klasser.

public – kan kommas åt från kod UTANFÖR och innanför klassen.

Detta gäller för funktioner och variabler.

Sätt standardvärden med konstruktor

Om du har programmerat i någon annan OOP språk som t.ex. Java, känner du säkert till konstruktor metoder. Dom heter oftast samma som klassen men i PHP har man ett enhetligt namn för den; construct (den hette samma som klassen i tidigare versioner av PHP).

construct anropas automatiskt när ett objekt skapas av en klass, och det är gotdytckligt vilken kod du lägger i metoden, men vanligen är det kod som initierar objektet genom att ge standardvärden till medlemsvariabler och anropa metoder.

Vi skriver in en __construct metod i vår klass:

Observera att den har två understreck i början. Construct metoden används enbart vid skapande av ny objekt, så den bör inte returnera något.

 

__destruct()

Det finns även en __destruct() metod som anropas automatiskt när ett objekt förstörs. I metoden kan man då avsluta saker som inte behövs längre, som att stänga öppna filer, eller databaser.

$this & self::

Använd $this för att hänvisa till det aktuella objektet. Använd self för att hänvisa till den aktuella klassen. $this refererar till en instans av en klass. Men det finns också något som kallas statiskt tillstånd, vilket är densamma för alla förekomster av den klassen. self:: är åtkomst nyckelordet för dessa attribut och funktioner.

Definitioner:

  • Class – detta är en användardefinierad datatyp, som omfattar lokala funktioner samt tillhörande lokal data i form av egenskaper. Du kan tänka på en klass som en mall för att göra många exemplar av samma typ av objekt   (instans av klass).
  • Objekt – en individuell instans av datastrukturen som definieras av en klass. Du definierar en klass en gång och gör sedan så många objekt du behöver, vilka härrör från klassen. Objekt är också kända som instanser av klasser.
  • Objekt Ortienterad Programmering – betyder att man klumpar ihop funktionalitet som hör ihop i klasser som kan innehålla medlemsvariabler och funktioner som man modifierar instanser av klassen genom objekt som skapats av klasserna.
  • Medlemsvariabler – dessa är de variabler som definierats i en klass. Denna data kommer att vara osynlig utanför klassenen men kan nås via medlemsfunktioner. Dessa variabler kallas för egenskaper av objektet när ett objekt har skapats.
  • Medlemsfunktioner – dessa är funktioner definierade i en klass och används för att komma åt data som hör till  objektet.
  • Close coupling – kod som är sammanlänkad och beroende av de olika delarna i applikationen.
  • Loose coupling – kod som inte är beroende av varandra och skrivs i individuela block
  • Procedural  – betyder att koden läses rad efter rad i ett linjärt flöde
  • Arv – När en klass definieras genom utökning av en befintlig föräldraklass, så det kallas det för nedärvning (inheritance). En barn-klass ärver alla eller några medlemsfunktioner och variabler från dess förälder-klass.
  • Förälder-klass – en klass som en barn-klass ärver från. Detta kallas också en basklass eller superklass.
  • Barnklass – en klass som ärver från en annan klass. Detta kallas också en subklass eller deriverad klass.
  • Subklass – är en barnklass.
  • Superklass – är en förälderklass
  • Extend –  en barnklass extend en förälderklss.
  • Data Abstraktion – en representation av data där detaljerna av genomförandet är dolda (abstraherade).
  • Query – Syftar till söknings strängar som används för att hämta databas poster som matchar angivna kriterier, t.ex. ”SELECT * FROM users ORDER BY id”
  • Polymorfism – detta är ett objektorienterat koncept där samma funktion kan användas för olika ändamål. Till exempel funktionsnamn förblir desamma men det kan ta olika antal argument och kan göra olika uppgifter.

Lämna en kommentar

E-postadressen publiceras inte. Obligatoriska fält är märkta *