Volaní base implementace metody na instanci odvozené třídy

Tomáš Holan       6. 11. 2013       C#, Reflexe       63360 zobrazení

Polymorfismus v jazyku C# striktně zajišťuje, že na instanci odvozené třídy je vždy volána přepsaná (override) implementace virtuální metody. Toto platí nejen například při přetypování dané instance zpět na typ základní třídy, ale i při volání metody základní třídy pomoci reflection.

Oboje demonstruje následující příklad:

class Base
{
    public virtual void Foo() { Console.WriteLine("Base"); }
}

class Derived : Base
{
    public override void Foo() { Console.WriteLine("Derived"); }
}

public static void Main()
{
    Derived d = new Derived();

    Base b = (Base)d;
    b.Foo();

    typeof(Base).GetMethod("Foo").Invoke(d, null);
    Console.ReadLine();
}

Pokaždé je tedy zavolána metoda Derived.Foo, nikoliv Base.Foo.

V normálních případech se snad ani nestane, že by jsme záměrně chtěli toto pravidlo porušit, a potřebovali zvenku na instanci odvozené třídy zavolat skrytou implementaci ze třídy základní. Pokud se do takové situace dostaneme, bude to zpravidla tím, že máme chybný návrh hierarchie našich tříd apod.

Pokud tedy chcete na odvozené třídě base implementaci metody zavolat, obecně platí: Nechtějte to a nedělejte to.

Přestože platí výše uvedené, jak lze takové volání udělat?

Jde to, a to dokonce i bez nutnosti modifikace IL (kdy by se v runtime na Derived třídě “dogenerovala” nová metoda zpřístupňující base.Foo) a podobných záležitostí. Jak na to ukazuje následující kód:

public static void Main()
{
    Derived d = new Derived();

    var method = typeof(Base).GetMethod("Foo");
    IntPtr ftn = method.MethodHandle.GetFunctionPointer();
    var action = (Action)Activator.CreateInstance(typeof(Action), obj, ftn);

    action();
}

Zde se na instanci třídy Derived skutečně zavolá metoda Base.Foo.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

???

Tiez som nepochopil co chcel autor povedat tymto postom.

Ze nemozem z potomka volat bazovu metodu? - Ved to je zakladna sucast OOP.

class Base
{
    public virtual void Foo() { Console.WriteLine("Base"); }
}

class Derived : Base
{
    public override void Foo() { Console.WriteLine("{0} and Derived", base.Foo()); }
}
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Použití klíčového slova base (MyBase ve VB.NET) v implementaci odvozené třídy článek nijak nerozporuje, to je samozřejmě naprosto standardní, správné a běžné.

Článek se zabývá reflexí a tím jestli lze principy OOP při volání metody odvozené třídy záměrně porušit (s tím že by jsme to ale neměli dělat).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Volání základní metody

Pokud tedy chcete na odvozené třídě base implementaci metody zavolat, obecně platí: Nechtějte to a nedělejte to.

A to jako proč? Zvenčí třídy pro to důvod obvykle není, zevnitř třídy se to mnohokrát hodí, k tomu účelu je ve VB.NET klíčové slovo MyBase, v C# už si přesně nepamatuju (base?).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Použití klíčovéno slova base (MyBase ve VB.NET) v implementaci odvozené třídy článek nijak nerozporuje, to je samozřejmě naprosto standardní, správné a běžné.

Článek se zabývá reflexí a to jednak tím, že ani tou k porušení OOP principů při volání metody odvozené třídy nedojde, a jednak tím, že pokud by jsme tento princip záměrně porušit chtěli, tak to dokážeme, jen by jsme to neměli dělat.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback