c# poliformizm i sealed -- dlaczego tak to działa

0

Witam Wszystkich
Od jakiegoś czasu staram się pisać w C# i mam pewną kwestię, którą nie do końca kumam.
mam oto zadeklarowane ćwiczebnie klasy

    public class A
    {
        public virtual string pisz(bool showBase = false)
        {
            return "Klasa A";
        }
    }
    public class B:A
    {
        public override string pisz(bool showBase = false)
        {
            return "Klasa B--"+ ((showBase == true) ? base.pisz() + "." : "");
        }
    }
    public class C:B
    {
        public **sealed** override string pisz(bool showBase = false)
        {
            return "Klasa C--" + ((showBase == true) ? base.pisz() + "." : "");
        }
    }
    public class D:C
    {
        public **new** string pisz(bool showBase=false)
        {
            return "Klasa D--"+((showBase==true)?base.pisz() + ".":"");

        }
    }

tak, że A jest klasą nadrzędną bazową dla B, C dziedziczy z B, a D dziedziczy z C. Z tymże w klasie C mam metodę która jest sealed i zgodnie z tym nie powinno być możliwości jej nadpisania. Teraz tworzę obiekty jak poniżej:

            A a = new A();
            B b = new B();
            C c = new C();
            D d = new D();

            A aa = new A();
            A ab = new B();
            A ac = new C();
            A ad = new D();

            txtConsole.Text += "\r\n" + a.pisz(true);
            txtConsole.Text += "\r\n" + b.pisz(true);
            txtConsole.Text += "\r\n" + c.pisz(true);
            txtConsole.Text += "\r\n" + d.pisz(true);

            txtConsole.Text += "\r\n---------------------------------";
            txtConsole.Text += "\r\n" + aa.pisz(true);
            txtConsole.Text += "\r\n" + ab.pisz(true);
            txtConsole.Text += "\r\n" + ac.pisz(true);
            txtConsole.Text += "\r\n" + ad.pisz(true);
            txtConsole.Text += "\r\n---------------------------------";
            txtConsole.Text += "\r\n" + ad.pisz();

I w pierwszym sposobie (obiekty a,b,c,d) gdzie typem obiektu jest jego klasa to wynikiem działania jest:

Klasa A
Klasa B--Klasa A.
Klasa C--Klasa B--.
Klasa D--Klasa C-->

Natomiast w drugim sposobie gdzie typem jest A (obiekty aa,ab,ac,ad) wynik to:

Klasa A
Klasa B--Klasa A.
Klasa C--Klasa B--.
Klasa C--Klasa B--.>

Czyli, wygląda na to, że przy wywołaniu obiektu d.pisz() wywoływana jest nadpisana metoda pisz w klasie D, natomiast w ad.pisz() wywoływana jest metoda nienadpisana.

Może mi ktoś wyjaśnić dlaczego

Dziękuję i pozdrawiam.
Tomek

6

Wywołanie d.pisz() to wywołanie po prostu metody zdefiniowaną w klasie D (tej z modyfikatorem new).
Wywołaniead.pisz() to wywołanie polimorficzne, a więc zostanie zawołana najbardziej pasująca metoda z hierarchii dziedziczenia. W tym przypadku metoda z klasy C, bo to ostatnia metoda z override. Metoda w klasie D jest poza hierarchą (dzięki new).

0

Ok dzięki, czyli zapis ten i użycie new w tym przypadku jest bez sensu, bo czy można wywołać tą metodę z klasy D przy deklaracji jako typ A tak jak to ma miejsce w obiekcie ad ?? i jeszcze co oznacza, że metoda jest poza hierarchią ? czy jest możliwość dostania się do niej ??

0
Tomek napisał(a):

Ok dzięki, czyli zapis ten i użycie new w tym przypadku jest bez sensu, bo czy można wywołać tą metodę z klasy D przy deklaracji jako typ A tak jak to ma miejsce w obiekcie ad ??

Jak widać nie można. Ale to nie znaczy, że to jest bez sensu. To jest po prostu taki mechanizm języka, który może się czasem przydać.

i jeszcze co oznacza, że metoda jest poza hierarchią ?

Chodziło mi o to, że nie bierze udziału w polimorifcznym wywoływaniu jak to się dzieje w przypadku metod, które są override.

czy jest możliwość dostania się do niej ??

No przecież się "dostałeś", bo ją wywołałeś.

0

może źle sprecyzowałem, chodziło mi o metodę pisz() z klasy D, bo w tej chwili dla obiektu ad wywoływana jest pisz() z klasy C.
Spróbowałem dostać się do tej metody przez rzutowanie ((D)ad).pisz(true); czy to właściwy sposób ??

Dzięki.

0

Tak, właściwy - nie da się inaczej zawołać metody z klasy D niż zawołać ją na jej obiekcie tej klasy. Zamiast rzutować możesz też od razu zadeklarować ad jako zmienną typu D, a nie A.

1 użytkowników online, w tym zalogowanych: 0, gości: 1