I Java används abstrakta klasser och gränssnitt som centrala verktyg för att åstadkomma abstraktion. Abstraktion inom objektorienterad programmering innebär att man döljer detaljerna i hur något är implementerat för dem som använder det.
Genom abstraktion kan man veta vilka funktioner som finns tillgängliga, men man behöver inte känna till de underliggande stegen för hur dessa funktioner faktiskt utförs.
Låt oss nu granska dessa två koncept mer i detalj för att förstå deras användningsområden och varför de är så viktiga.
Abstrakt Klass
En abstrakt klass är en klass som inte direkt kan skapa objekt, den kan också innehålla eller inte innehålla abstrakta metoder. En abstrakt metod är en metod som deklareras utan en konkret implementation.
Ett exempel på en abstrakt klass är GraphicObject som används i Java – Oracle.
En abstrakt klass definieras genom att placera nyckelordet ”abstract” framför ordet ”class”.
abstract class AbstraktKlass { void utfor() { System.out.println("Utförd"); } }
En abstrakt klass kan utökas av andra klasser, vilket innebär att den kan fungera som en basklass för subklasser.
abstract class AbstraktKlass { void utfor() { System.out.println("Utförd"); } } class UtvidgadAbstraktKlass extends AbstraktKlass { void nyMetod() { System.out.println("Ny"); } @Override void utfor() { System.out.println("Omdefinierad"); } }
Abstrakta klasser är praktiska för att definiera gemensamma metoder som används av flera klasser som ärver från den abstrakta klassen. Möjligheten att definiera abstrakta metoder gör dessa klasser ovärderliga för klasser som har metoder med liknande syfte men olika utföranden. Låt oss illustrera detta med ett exempel.
Tänk på en bil som har grundläggande funktioner som start, stopp och backning. Dessa funktioner är gemensamma för alla fordon.
Men hur hanteras mer avancerade funktioner som självkörande? Implementationen för dessa kan skilja sig markant mellan olika bilmodeller. Låt oss se hur detta kan översättas till objektorienterad kod.
Vi börjar med att skapa en basklass för bilar som kommer att utökas av olika typer av bilar.
abstract class Bil { void starta() { // implementation System.out.println("Startar bilen"); } void stoppa() { // implementation System.out.println("Motorn stannar"); } void backa() { // implementation System.out.println("Backläge aktiverat"); } abstract void sjalvkora(); }
Metoderna `starta()`, `stoppa()` och `backa()` är standardfunktioner för alla bilar, och deras implementation definieras i basklassen. Däremot kan självkörningsfunktionen variera beroende på bilmodell. Därför kan `sjalvkora()` definieras som en abstrakt metod och implementeras på olika sätt i subklasserna.
class BilTypA extends Bil { @Override void starta() { super.starta(); } @Override void stoppa() { super.stoppa(); } @Override void backa() { super.backa(); } void sjalvkora() { // specifik implementation System.out.println("Typ A självkörningsläge aktiverat"); } }
class BilTypB extends Bil { // ...liknande metoder void sjalvkora() { // specifik implementation // skiljer sig från CarTypeB System.out.println("Typ B självkörningsläge aktiverat"); } }
Det är viktigt att notera att om en subklass inte implementerar alla abstrakta metoder som definieras i basklassen, måste även subklassen deklareras som abstrakt.
Gränssnitt
Ett gränssnitt är ett sätt att specificera vilka metoder en klass måste implementera. Om vi tar bilexemplet igen, så har alla bilar grundläggande funktioner, som att starta, köra och stanna.
Om ett gränssnitt för en bil implementeras i en klass, så måste alla dessa metoder implementeras för att bilen ska fungera korrekt och säkert.
Precis som abstrakta klasser kan man inte instansiera objekt från ett gränssnitt. Gränssnitt kan ses som helt abstrakta klasser, eftersom de bara innehåller abstrakta metoder, det vill säga metoder utan implementation.
Ett gränssnitt skapas med nyckelordet `interface`.
interface BIL { void starta(); void stoppa(); void kora(); }
En klass implementerar ett gränssnitt genom att använda nyckelordet `implements` vid definitionen av klassen.
class BilTypB implements BIL { public void starta() { System.out.println("Startad"); } public void stoppa() { System.out.println("Stoppad"); } public void kora() { System.out.println("Kör"); } }
Likheter
Den enda likheten mellan abstrakta klasser och gränssnitt är att man inte kan skapa objekt av dem.
Skillnader
Abstrakt klass | Gränssnitt | |
Arv och implementering | Endast en abstrakt klass kan ärvas av en klass. | Flera gränssnitt kan implementeras av en klass. |
Variabeltyper | Den kan ha slutliga, icke-slutliga, statiska och icke-statiska variabler. | Den kan endast ha statiska och slutliga variabler. |
Metodtyper | Den kan innehålla både abstrakta och icke-abstrakta metoder. | Den kan bara innehålla abstrakta metoder, men statiska metoder är ett undantag. |
Åtkomstmodifierare | En abstrakt klass kan ha en åtkomstmodifierare. | Metodsignaturerna som definieras i gränssnittet är offentliga som standard. Ett gränssnitt har ingen åtkomstmodifierare. |
Konstruktörer och destruktorer | Den kan deklarera konstruktörer och destruktorer. | Den kan inte deklarera konstruktörer eller destruktorer. |
Hastighet | Snabb | Långsam |
Skillnader mellan abstrakt klass och gränssnitt
När ska man använda abstrakt klass och gränssnitt?
Använd abstrakta klasser när:
- Du vill dela gemensamma metoder och attribut mellan flera relaterade klasser.
- Du behöver deklarera icke-statiska och icke-slutliga attribut för att kunna ändra tillståndet hos objekten som de är knutna till.
Använd gränssnitt när:
- Du vill specificera vilket beteende en klass ska ha utan att definiera hur det ska utföras.
- Du vill tvinga en klass att implementera ett visst antal metoder för att fungera korrekt.
Slutord
Gränssnitt är framförallt viktiga för att skapa API:er, eftersom de ger en struktur för hur funktionalitet ska implementeras utan att detaljer kring själva genomförandet behöver specificeras.
Abstrakta klasser är mest användbara när man vill dela gemensam logik i form av både abstrakta och icke-abstrakta metoder mellan flera klasser, vilket ökar kodåteranvändbarheten.
Vill du lära dig mer om Java? Då finns det en rad onlinekurser tillgängliga. Förbereder du dig för en intervju inom Java? Här är några intervjufrågor om objektorienterad programmering.