tisdag 20 mars 2012

Vad är skillnaden mellan en abstract- och interface class?

Ett koncept som kan vara en aning svårt att greppa är klasser av typen abstract och interface. Det är inte helt lätt att till en början förstå hur det fungerar och absolut inte när det kan vara användbart. Det tog mig ett tag innan ett Eureka!-ögonblick slutligen infann sig. Jag visste länge hur det fungerade, alltså hur det praktiskt skulle kodas, men inte när det passade.

Wassily Kandinsky, On White 2, 1923

Samma sak gällde för övrigt  när jag först lärde mig klasser i programering. Kanske för att det första språket jag lärde mig var PHP som är ett väldigt löst strukturerat språk. I Java är klasser mer naturligt och direkt nödvändigt. I PHP klarar man sig länge med enbart funktioner och fält/vektorer, hädanefter arrays.

I PHP kan du exempelvis skapa multidimensionella arrays med blandad data, medan du i Java enbart kan skapa arrays av en typ. Java är naturligt objekt orienterat.

Låt oss titta på ett snabbt exempel:

$user[0]['name'] = 'Jamie';
$user[0]['age'] = 27;
$user[0]['isRegisterd'] = true;


$user[1]['name'] = 'Jamie';
$user[1]['age'] = 27;
$user[1]['isRegisterd'] = true;


Här har vi skapat en multidimensionell array i PHP som innehåller tre olika datatyper; String, Integrer och Boolean.
I Java kan vi inte göra detta, istället får vi skapa en klass som heter User som sedan innehåller variabler som kan hålla de olika datatyperna. Sedan kan vi skapa en objekt array av typen User med information om de olika personerna.

User[] userArray = new User[2];

User-klassen har dessutom antagligen diverse set och get metoder för att spara data. Så när vi lägger till en ny person skulle det antagligen se ut enligt följande:

user[0] = new User();
user[0].setName("Jamie");
user[0].setAge(27); 
user[0].setIsRegisterd(true);

eller om vi har skapat en construct-method så kanske vi hade gjort;

user[0] = new User("Jamie", 27, true);

Men nog om skillnaden mellan PHP och Java. Vad jag ville förklara är varför det kanske inte är lika naturligt för någon som inte börjat med att lära sig ett riktigt objekt orienterat språk.


Vad är då en abstract och interface klass? Och vad är skillnaden?

Man kan säga att både abstract och interface är klass-mallar. De berättar hur övriga klasser som bygger (implements/extends) på dessa ska se ut och fungera. En abstract klass kan innehålla färdiga metoder medan ett interface bara kan sätta strukturen för hur övriga klasser ska byggas. Men en klass kan enbart bygga/ärva (extends) på en abstract-klass men implementera (implements) flera interface-klasser.

Nu är det inte riktigt så lätt. För att jag inte skall bli häng för min terminologi så ska man kanske förtydliga att medan en abstract-klass faktiskt är en klass så är ett interface inte en klass utan snarare ett så kallat object interface. De skrivs lite olika också.

Interface:

interface Database {
   public function fetchRow($table, $id);


Abstract:

abstract class Database {
   abstract 
public function fetchRow($table, $id);
}


Vi kan sedan använda ovan enligt följande:

//Interface
class MySQL implements Database {
   public function fetchRow($table, $id){
      //Kod...
   }
}

//Abstract
class MySQL extends Database {
   public function fetchRow($table, $id){
      //Kod...
   }
}


I båda fallen ovan kräver vi att det ska finnas en fetchRow-metod. I mångt och mycket är exemplet ovan identiska med varandra.

En bra metafor som förklarar skillnaden ganska bra är den som följer;

Alla personer i flygvapnet går en pilotutbildning för att bli piloter. Men bara för att de gått en pilot utbildning så betyder detta inte att de har behörighet att flyga något. De måste först utbilda sig i en flygplantyp, exempelvis F-16 eller T-38. De är alltså en pilot (abstrakt klass) och blir sedan en F-16 pilot (klass). Många inom flygvapnet har dock andra uppgifter också så som att vara Säkerhetsofficer (interface klass). Men vem som helst kan vara detta, det är inte unikt för piloter.

En pilot är generellt sett en person som kan manöverera flygplan. Han/hon har grundläggande kunskap om hur man flyger. En F16 pilot har samma egenskaper och kunskap men är specialiserad på flygplanstypen F-16.

Pilot = Abstrakt klass
F-16 pilot = Klass
Säkerhetsofficer = Interface

Ovan är lånat med viss modifikation och översättning från: http://stackoverflow.com/questions/761194/interface-vs-abstract-class-general-oo

Ett praktiskt exempel skulle exempelvis vara om man skapar en applikation som ska fungera med olika typer av databaser så som MySQL och MS Access.
Då skulle man fördelaktigt kunna skapa en abstract-klass som heter Database med grundläggande metoder för hantering av data som ska skickas till och hämtas från en databas. Man kan även skapa en Interface som heter Database som berättar vilka metoder som måste finnas och hur de ska användas. Vi vill kan till exempel bestämma att det ska finnas en metod som heter fetchRow() som har variablerna table och id.

Sedan kan vi skapa två klasser, en för MySQL och en för MS Access som extends och implements våra abstract- och interface-klasser. Vi garanterar på detta vis att vi kan använda dessa två klasser i vårt program oavsett vilken typ av databas vi sedan väljer att arbeta med. Vi har samma in och ut variabler och får samma resultat även om koden för att utföra de olika anropen är olika. Vi garanterar att klassernas struktur ser ut och fungerar på ett förutbestämt sett.

Läs mer:

Object Interfaces, PHP.net (elektronisk) <http://php.net/manual/en/language.oop5.interfaces.php>
Class Abstraction, PHP.net (elektronisk) <http://www.php.net/manual/en/language.oop5.abstract.php>







Inga kommentarer:

Skicka en kommentar