C# Klasser polymorfism (dynamisk bindning)
Begreppet Polymorfism
Vi såg i förra delen (Arv) att vi hade olika namn på skriv_ut-metoderna i de olika klasserna. Vi var tvugna att hela tiden hålla reda på vilket objekt vi jobbar med. Nu ska vi skapa referenser till objekt av superklassen som i sin tur kan referera till objekt av subklasserna.
Om vi skapar en metod i alla klasserna som har samma namn och samma antal och typer av parametrar.
Då kommer
typen av objekt styra vilken av metoderna (de med samma namn) som anropas. Först undersöks det om metoden finns i klassen till det objekt som referensen pekar på. Om det inte finns någon metod med rätt namn där så vandrar den uppåt i hierarkin och letar tills den kommer till basklassen.
Virtual - Override
För att polymorfismen ska fungera måste vi lägga till virtual på metoden i basklassen och override på metoderna i subklasserna.
Vårt tidigare Elev-exempel nu utbyggt med polymorfism
Vi lägger till virtual på metoden skriv_ut_data .
class Elev
{
// här deklareras gömda (utanför objektet) variabler och metoder som "private"
private string namn;
private int points;
//klassvariabel
public static int antal = 0;
// här deklareras synliga (utanför objektet) variabler och metoder som "public"
public void skriv_in_data()
{
Console.Write(" Elevnamn: ");
namn = Console.ReadLine();
Console.Write(" Poäng: ");
points = int.Parse(Console.ReadLine());
}
public virtual void skriv_ut_data()
{
Console.WriteLine("\nElevnnamn: " + namn + " Poäng: " + points);
}
public void increase_points(int x)
{
points += x;
}
private void antalElever()
{
antal++;
}
public void skrivUtNamnOchAntalElever()
{
Console.WriteLine("========================");
Console.WriteLine(" Namn: " + namn);
Console.WriteLine(" Antal elever: " + antal + " st");
Console.WriteLine("========================");
}
//klassmetod
public static void skrivUtAntalElever()
{
Console.WriteLine("========================");
Console.WriteLine(" Antal elever: " + antal + " st");
Console.WriteLine("========================");
}
// Konstruktorer
public Elev()
{
antal++;
namn = "ingen";
points = 0;
}
public Elev(string n)
{
antalElever();
namn = n;
points = 0;
}
public Elev(string n, int p)
{
antalElever();
namn = n;
points = p;
}
}
I subklassen VanligElev byter vi namn på metoden skriv_ut_data_vanlig till samma namn som basklassen skriv_ut_data, samt att vi lägger till override .
class VanligElev : Elev {
int skapNr;
// Konstruktor 1
public VanligElev() : base ( ) {
skapNr=0;
}
// Konstruktor 2
public VanligElev(string fnamn, int p, int snr) : base (fnamn, p)
{
skapNr=snr;
}
// Metoden skriver ut informationen om den vanliga eleven.
public override void skriv_ut_data()
{
string info;
base.skriv_ut_data( );
info = "Elevens skåpnummer : " + skapNr +
"\nEleven är elev på vanliga gymnasiet.";
Console.WriteLine(info);
}
}
I subklassen VanligElev byter vi namn på metoden skriv_ut_data_distans till samma namn som basklassen skriv_ut_data, samt att vi lägger till override .
class DistansElev : Elev {
string handledare;
// Konstruktor 1
public DistansElev() : base( )
{
handledare = "NoName";
}
// Konstruktor 2
public DistansElev(string fnamn, string hnamn) : base (fnamn)
{
handledare=hnamn;
}
// Konstruktor 3
public DistansElev(String fnamn, int p, string handl):base (fnamn,p)
{
handledare = handl;
}
// Metoden skriver ut informationen om distanseleven.
public override void skriv_ut_data()
{
string info;
base.skriv_ut_data();
info = "Handledaren heter : " + handledare +
"\nEleven är en distanselev.";
Console.WriteLine(info);
}
} // end class DistansElev
Till slut huvudprogrammet som testar att skapa lite olika typer av objekt.
Nu omskrivet för att visa på polymorfismens egenskaper.
// HUVUDPROGRAMMET
class Program
{
static void Main(string[] args)
{
Elev[ ] skola = new Elev[5];
skola[0] = new Elev("Janne Långben", 2);
VanligElev student1 = new VanligElev("Musse Pigg", 123, 207);
skola[1] = student1;
DistansElev student2 = new DistansElev("Kalle Anka", 111, "Fantomen");
skola[2] = student2;
skola[3] = new VanligElev("Mimmi Pigg", 123, 207);
skola[4] = new DistansElev("Kajsa Anka", 222, "Fantomen");
// Skriver ut information om studenterna.
skola[0].skriv_ut_data();
skola[1].skriv_ut_data();
skola[2].skriv_ut_data();
skola[3].skriv_ut_data();
skola[4].skriv_ut_data();
skola[4] = skola[1];
skola[4].skriv_ut_data();
Console.ReadLine();
}
}
Källor
Skarp programmering med C#, 2011, Jan Skansholm
Microsoft Visual C# 2010, 2010, John Sharp