Generisk programmering i C# på .net del 3

Polymorfi

Poly = mange

Morf = form

Altså mange former.

En klasse der er nedarvet fra en anden kan have form som sig selv eller én klasse den har nedarvet.

 

Har man eks. Defineret en field klasse og nedarvet denne klasse både til et stringfield og et multivaluefield, så er det muligt at have en liste af fields.

Field er en abstract base klasse, som der ikke findes en kontret implementering af.

Har man listen af felter, er det muligt at lave en metode, der hedder GetFieldValue(), denne returnerer en streng, med værdien af klassen.

Nu er det muligt at loop over alle felter i listen, og kalde GetFieldValue() på samtlige fields, der både kan være stringfields og multivaluefields. Ved hjælp af polymorfi kaldes GetFieldValue() ikke på Field klassen, da denne jo ikke kan vide hvordan man får feltværdien fra alle slags felter, der i fremtiden kan kaldes.

 

Dette kan ordnes ved at lave metoden i field klassen virtuel, sådan her:

 

public virtual string GetFieldValue()

{

     return string.Empty;

}

 

Det betyder at metoden skal behandles virtuelt, hvilket igen betyder at det er 'den mest nedarvede' metode der kaldes.

Har man altså et hieraki hvor klassen A er base klassen, herfra nedarves B, og igen C, og D.

 

På A findes en virtuel metode Method1(). Denne er defineret i både B og C med override keywordet.

 

Kaldes nu en klasse som følger:

 

            A instansC = new C();

            instansC.Method1();

 

Selvom vi har en klasse af typen A kaldes nu metoden Method1() på klasse C, da vi egentlig har en klasse af typen C.

Her behandles klassen altså som en anden form end den den egentlig har.

På samme måde kan man kalde på en instans af typen C, kaldes Method1() på denne instans, kaldes instansen på C, da det er den mest nedarvede metode.

 

Laver man nu en metode på klassen D, som hedder Method1() vil man få en advarsel fra compileren. Man har nu mulighed for at lave metoden som override eller new.

Laves metoden som override kaldes den virtuelt.

 

Laves metoden derimod new, indgår den ikke i det virtuelle nedarvningshieraki.

Dette betyder at laver man en  instans A = new D(); Og kalder metoden på denne vil man få den fra C, da den er den mest nedarvede i det virtuelle nedarvnings hieraki. Metoden på D er en helt ny metode og ikke den som findes på de øvrige klasser

Her er et eksempel:

public class A

    {

        public virtual string Method1()

        {

            return "From class A";

        }

    }

 

    public class B : A

    {

        public override string Method1()

        {

            return "From class B";

        }

    }

 

    public class C: B

    {

        public override string Method1()

        {

            return "From class C";

        }

    }

    public class D : C

    {

        public new string Method1()

        {

            return "From class D";

        }

    }

 

class Program

    {

        static void Main(string[] args)

        {

            List<A> listOfAs = new List<A>();

            listOfAs.Add(new A());

            listOfAs.Add(new B());

            listOfAs.Add(new C());

            listOfAs.Add(new D());

 

            foreach (A instans in listOfAs)

            {

                Console.WriteLine(instans.Method1());

            }

 

            Console.WriteLine();

 

            A instansOfAA = new A();

            A instansOfAB = new B();

            A instansOfAC = new C();

            A instansOfAD = new D();

            C instansOfCD = new D();

            D instansOfDD = new D();

 

            Console.WriteLine(instansOfAA.Method1());

            Console.WriteLine(instansOfAB.Method1());

            Console.WriteLine(instansOfAC.Method1());

            Console.WriteLine(instansOfAD.Method1());

            Console.WriteLine(instansOfCD.Method1());

            Console.WriteLine(instansOfDD.Method1());

        }

    }

Output fra denne bliver:

From class A

From class B

From class C

From class C

 

From class A

From class B

From class C

From class C

From class C

From class D

Som det ses stoppes det virtuelle nedarvningshieraki ved D, da denne erklæres new.

Envidere ses det at selv om det er ene A’er vi har i listen så kaldes de respektive metoder virtuelt, og altså på den klasse som de reelt er.

Har du svært ved at forstå det med polymorfi, så prøv at compilere eksemplerne, og rod lidt med at lave nye virtuelle funktioner osv.