Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lære Polymorfisme | OOP-Prinsipper
C# Utover Det Grunnleggende

bookPolymorfisme

Begrepet Polymorfisme betyr "forekommer i flere forskjellige former". I objektorientert programmering refererer polymorfisme til evnen en klasse har til å tilby et felles grensesnitt for sine avledede klasser, samtidig som hver avledet klasse kan implementere spesifikke oppføringer for de arvede metodene.

Vanligvis når du oppretter et objekt av en klasse, lager du en variabel for å holde referansen til det objektet. Typen til variabelen er som regel klassen til det objektet.

For eksempel:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

Du kan imidlertid også opprette en variabel av en baseklasse og lagre et objekt av en avledet klasse i den.

For eksempel:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

Attributtet breed til Dog-objektet er ikke tilgjengelig fordi når du lagrer Dog-objektet i en Mammal-variabel, blir det implisitt konvertert til Mammal. Dette betyr at du kun kan få tilgang til attributter og metoder som finnes i Mammal-klassen. Det betyr ikke at verdien lagret i breed-klassen er tapt, den er bare utilgjengelig og du kan si at den i praksis er skjult.

Du kan enkelt konvertere example til en Dog gjennom eksplisitt typekonvertering, og attributtet breed vil bli tilgjengelig igjen:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

For metoder finnes det imidlertid en ekstra funksjon kalt metodeoverstyring, som ligner noe på metodeoverlasting. Her definerer du i praksis en metode fra en baseklasse på nytt i en avledet klasse.

For eksempel kan du ønske at Mammal har en metode speak() slik at den skriver ut Woof! hvis den kalles fra et Dog-objekt, og Meow! hvis den kalles fra et Cat-objekt:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Advarslene du får ved denne kompileringen skyldes overlappende navn på metoder i foreldre- og barneklasser. I dette tilfellet er det overlapp mellom speak-metodene i klassene Cat og Mammal, samt mellom Dog og Mammal, noe som gir to advarsler.

Legg imidlertid merke til at m1, m2 og m3 til slutt utfører metoden definert i Mammal-klassen, fordi de er kastet til Mammal-objekter.

Hvis du ønsker at speak-metoden skal oppføre seg slik den gjør i sitt opprinnelige objekt, kan du ganske enkelt gjøre den om til en virtuell metode. En virtuell metode er en metode som lar deg overstyre seg selv fra avledede klasser på en slik måte at den spesifikke implementasjonen som kjøres bestemmes under kjøring basert på typen til det opprinnelige objektet.

For å gjøre en metode virtuell, legger du bare til nøkkelordet virtual før returtypen:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

For å lage en overstyrt implementasjon av denne metoden, bruk nøkkelordet override før returtypen i den avledede klassens implementasjon av den nye versjonen:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

La oss nå sette sammen de to kodestykkene og se hvordan det påvirker utskriften:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Du ser at i utskriften bruker m2 og m3 implementasjonen til henholdsvis Cat og Dog, fordi disse objektene opprinnelig var av typene Cat og Dog. Denne prosessen med å overskrive metoder slik at de oppfører seg basert på sin opprinnelige type, kalles polymorfisme.

En situasjon hvor dette kan være svært nyttig, er muligheten til å lagre objekter av flere ulike datatyper i ett enkelt array eller liste.

For eksempel:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. Hvilke to nøkkelord brukes ved metodeoverstyring?

2. Hva er riktig måte å gjøre en metode overstyrbar på?

question mark

Hvilke to nøkkelord brukes ved metodeoverstyring?

Select the correct answer

question mark

Hva er riktig måte å gjøre en metode overstyrbar på?

Select the correct answer

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 5. Kapittel 4

Spør AI

expand

Spør AI

ChatGPT

Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår

Suggested prompts:

Can you explain more about how polymorphism works in arrays or lists?

What are some real-world examples where polymorphism is useful?

Can you show how to implement polymorphism in another programming language?

Awesome!

Completion rate improved to 2.04

bookPolymorfisme

Sveip for å vise menyen

Begrepet Polymorfisme betyr "forekommer i flere forskjellige former". I objektorientert programmering refererer polymorfisme til evnen en klasse har til å tilby et felles grensesnitt for sine avledede klasser, samtidig som hver avledet klasse kan implementere spesifikke oppføringer for de arvede metodene.

Vanligvis når du oppretter et objekt av en klasse, lager du en variabel for å holde referansen til det objektet. Typen til variabelen er som regel klassen til det objektet.

For eksempel:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

Du kan imidlertid også opprette en variabel av en baseklasse og lagre et objekt av en avledet klasse i den.

For eksempel:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

Attributtet breed til Dog-objektet er ikke tilgjengelig fordi når du lagrer Dog-objektet i en Mammal-variabel, blir det implisitt konvertert til Mammal. Dette betyr at du kun kan få tilgang til attributter og metoder som finnes i Mammal-klassen. Det betyr ikke at verdien lagret i breed-klassen er tapt, den er bare utilgjengelig og du kan si at den i praksis er skjult.

Du kan enkelt konvertere example til en Dog gjennom eksplisitt typekonvertering, og attributtet breed vil bli tilgjengelig igjen:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

For metoder finnes det imidlertid en ekstra funksjon kalt metodeoverstyring, som ligner noe på metodeoverlasting. Her definerer du i praksis en metode fra en baseklasse på nytt i en avledet klasse.

For eksempel kan du ønske at Mammal har en metode speak() slik at den skriver ut Woof! hvis den kalles fra et Dog-objekt, og Meow! hvis den kalles fra et Cat-objekt:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Advarslene du får ved denne kompileringen skyldes overlappende navn på metoder i foreldre- og barneklasser. I dette tilfellet er det overlapp mellom speak-metodene i klassene Cat og Mammal, samt mellom Dog og Mammal, noe som gir to advarsler.

Legg imidlertid merke til at m1, m2 og m3 til slutt utfører metoden definert i Mammal-klassen, fordi de er kastet til Mammal-objekter.

Hvis du ønsker at speak-metoden skal oppføre seg slik den gjør i sitt opprinnelige objekt, kan du ganske enkelt gjøre den om til en virtuell metode. En virtuell metode er en metode som lar deg overstyre seg selv fra avledede klasser på en slik måte at den spesifikke implementasjonen som kjøres bestemmes under kjøring basert på typen til det opprinnelige objektet.

For å gjøre en metode virtuell, legger du bare til nøkkelordet virtual før returtypen:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

For å lage en overstyrt implementasjon av denne metoden, bruk nøkkelordet override før returtypen i den avledede klassens implementasjon av den nye versjonen:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

La oss nå sette sammen de to kodestykkene og se hvordan det påvirker utskriften:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Du ser at i utskriften bruker m2 og m3 implementasjonen til henholdsvis Cat og Dog, fordi disse objektene opprinnelig var av typene Cat og Dog. Denne prosessen med å overskrive metoder slik at de oppfører seg basert på sin opprinnelige type, kalles polymorfisme.

En situasjon hvor dette kan være svært nyttig, er muligheten til å lagre objekter av flere ulike datatyper i ett enkelt array eller liste.

For eksempel:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. Hvilke to nøkkelord brukes ved metodeoverstyring?

2. Hva er riktig måte å gjøre en metode overstyrbar på?

question mark

Hvilke to nøkkelord brukes ved metodeoverstyring?

Select the correct answer

question mark

Hva er riktig måte å gjøre en metode overstyrbar på?

Select the correct answer

Alt var klart?

Hvordan kan vi forbedre det?

Takk for tilbakemeldingene dine!

Seksjon 5. Kapittel 4
some-alt