Polymorfism betyder “många former”. Det låter dig behandla objekt av olika klasser på samma sätt — så länge de delar samma gränssnitt eller basklass.

Djur[] djur = { new Hund(), new Katt(), new Ko() };
for (Djur d : djur) {
    d.lat();   // Voff! Mjau! Mu!
}

Utan polymorfism hade du behövt en ful if-else-kedja för att avgöra vilket djur som gör vilket ljud.


Statisk vs Dynamisk Polymorfism

Det finns två typer av polymorfism:

TypOckså kallatNärExempel
StatiskÖverlagring (overloading)Vid kompileringFlera metoder med samma namn, olika parametrar
DynamiskÖverskuggning (overriding)Vid körningEn metod som beter sig olika beroende på objektets faktiska typ

Statisk polymorfism — Överlagring (Overloading)

Överlagring innebär att en klass har flera metoder med samma namn men olika parametrar:

public class Kalkylator {
    // Samma metodnamn, olika parametrar

    public int addera(int a, int b) {
        return a + b;
    }

    public double addera(double a, double b) {
        return a + b;
    }

    public int addera(int a, int b, int c) {
        return a + b + c;
    }
}

Kalkylator k = new Kalkylator();
k.addera(2, 3);            // anropar första
k.addera(2.5, 3.7);        // anropar andra
k.addera(1, 2, 3);         // anropar tredje

Regler för överlagring:

  • Olika antal parametrar
  • Olika typer på parametrar
  • Olika ordning på parametrar
  • Returtypen räknas inte — du kan inte överlagra bara på returtyp

Dynamisk polymorfism — Överskuggning (Overriding)

Överskuggning innebär att en subklass ger en ny implementation av en metod som ärvs från superklassen:

public abstract class Djur {
    public abstract void lat();
}

public class Hund extends Djur {
    @Override
    public void lat() {
        System.out.println("Voff!");
    }
}

public class Katt extends Djur {
    @Override
    public void lat() {
        System.out.println("Mjau!");
    }
}

// Dynamisk bindning — rätt metod väljs vid körning
Djur d1 = new Hund();
Djur d2 = new Katt();

d1.lat(); // Voff!
d2.lat(); // Mjau!

Kompilatorn vet bara att d1 och d2 är av typen Djur. Vid körning avgör JVM:en vilken konkret klass objektet har och anropar rätt metod.


Polymorfism via Interface

Interface är det mest flexibla sättet att uppnå polymorfism:

public interface Betalningsmetod {
    void betala(double belopp);
}

public class Kort implements Betalningsmetod {
    public void betala(double belopp) {
        System.out.println("Kortbetalning: " + belopp + " kr");
    }
}

public class Swish implements Betalningsmetod {
    public void betala(double belopp) {
        System.out.println("Swish-betalning: " + belopp + " kr");
    }
}

public class Faktura implements Betalningsmetod {
    public void betala(double belopp) {
        System.out.println("Faktura skickas på " + belopp + " kr");
    }
}

// Alla betalningsmetoder kan behandlas likadant
Betalningsmetod[] betalningar = {
    new Kort(), new Swish(), new Faktura()
};

for (Betalningsmetod b : betalningar) {
    b.betala(499.00);
    // Kortbetalning: 499.0 kr
    // Swish-betalning: 499.0 kr
    // Faktura skickas på 499.0 kr
}

instanceof och type-checking

Ibland behöver du veta vilken konkret typ ett objekt har:

Djur d = new Hund();

if (d instanceof Hund) {
    Hund h = (Hund) d;  // typomvandling (casting)
    h.hamtapport();
}

Varning: Överdriven användning av instanceof är en code smell — den bryter mot Open/Closed-principen och indikerar ofta att du borde använda polymorfism istället.

// DÅLIGT — istället för polymorfism
public void lat(Djur d) {
    if (d instanceof Hund) System.out.println("Voff!");
    else if (d instanceof Katt) System.out.println("Mjau!");
    else if (d instanceof Ko) System.out.println("Mu!");
}

// BRA — låt objektet bestämma
public void lat(Djur d) {
    d.lat(); // polymorfism!
}

Polymorfism och designmönster

Många designmönster bygger på polymorfism:

MönsterHur polymorfism används
StrategyOlika algoritmer via samma interface
StateOlika beteenden beroende på tillstånd
CommandOlika operationer via samma execute()
VisitorOlika operationer per elementtyp
ObserverAlla observatörer får samma notifiering
Factory MethodSubklasser bestämmer vilket objekt som skapas

Polymorfism i olika språk

SpråkAbstrakta metoderInterfaceDynamic dispatch
JavaabstractinterfaceDefault (virtual)
TypeScriptabstractinterfaceDefault
PHPabstractinterfaceDefault
C#abstractinterfacevirtual / override
C++= 0 (pure virtual)Rena abstrakta klasservirtual
Python@abstractmethodABCDefault (duck typing)

I C# måste du explicit markera metoder som virtual för att de ska kunna överskuggas — i Java, PHP och TypeScript är alla metoder virtual som standard.


Fortsätt till Abstrakta klasser och Interface.

Av Victor Hernandez från Bytebase.se