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:
| Typ | Också kallat | När | Exempel |
|---|---|---|---|
| Statisk | Överlagring (overloading) | Vid kompilering | Flera metoder med samma namn, olika parametrar |
| Dynamisk | Överskuggning (overriding) | Vid körning | En 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önster | Hur polymorfism används |
|---|---|
| Strategy | Olika algoritmer via samma interface |
| State | Olika beteenden beroende på tillstånd |
| Command | Olika operationer via samma execute() |
| Visitor | Olika operationer per elementtyp |
| Observer | Alla observatörer får samma notifiering |
| Factory Method | Subklasser bestämmer vilket objekt som skapas |
Polymorfism i olika språk
| Språk | Abstrakta metoder | Interface | Dynamic dispatch |
|---|---|---|---|
| Java | abstract | interface | Default (virtual) |
| TypeScript | abstract | interface | Default |
| PHP | abstract | interface | Default |
| C# | abstract | interface | virtual / override |
| C++ | = 0 (pure virtual) | Rena abstrakta klasser | virtual |
| Python | @abstractmethod | ABC | Default (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