Polymorfisme
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
123Dog 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
1234567891011121314151617181920212223242526272829303132using 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
12345678910111213141516171819202122232425262728293031323334353637383940using 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
1234567class 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
123456789101112131415class 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
123456789List<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å?
Takk for tilbakemeldingene dine!
Spør AI
Spør AI
Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår
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
Polymorfisme
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
123Dog 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
1234567891011121314151617181920212223242526272829303132using 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
12345678910111213141516171819202122232425262728293031323334353637383940using 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
1234567class 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
123456789101112131415class 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
123456789List<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å?
Takk for tilbakemeldingene dine!