Jason. Cała informatyka w jednym miejscu!

Omówiliśmy niedawno czym jest przeciążanie metody w języku C#. Spojrzymy teraz na mechanizm, który posiada BARDZO podobną nazwę, a polega na czymś zupełnie innym. Tym razem jednak potrzebujemy wiedzy o odrębnym słowie kluczowym. Oto przed Wami "override" w języku C# i ukazanie przesłonięcia właściwości oraz metody (a także po co to wszystko jest).

"OVERRIDE" W JĘZYKU C#, CZYLI PRZESŁANIANIE W KRYSTALICZNEJ FORMIE!

Przedstawiciele języka Java, kojarzycie? Adnotacja "@Override", pisanie pod spodem nowej wersji metody, te sprawy :):

@Override
public void doSomething()
{
	System.out.println("Przesłonięta wersja metody klasy bazowej!");
}

Jeśli drapiecie się teraz po głowie, to zignorujcie to i zjedźcie do poniższego nagłówka :). To samo tyczy się tych, którzy doskonale wiedzą po co się stosuje, gdyż C# w tym przypadku rządzi się troszkę swoimi prawami i różni się od Javy pod tym względem dosyć mocno. Przejdę do gruntownego wyjaśnienia.

PRZESŁANIANIE Z DEFINICJI

Pod terminem "przesłanianie" kryje się technika nadpisywania treści funkcji albo właściwości przez klasę potomną. Są takie sytuacje, w których nie podoba nam się zachowanie albo dana jaką klasa bazowa przekazuje swoim potomkom i właśnie wtedy przydaje się nam przesłanianie w stosunku do metody albo właściwości, bo to są dwie najczęstsze konstrukcje podlegające przesłonięciu (jeśli nie jedyne dozwolone).

Przesłanianie wykorzystywane jest także podczas obowiązkowego definiowania treści metod abstrakcyjnych jakie oferuje klasa bazowa, która sama także jest wtedy abstrakcyjna (jeżeli klasa dysponuje czymkolwiek abstrakcyjnym, ona także musi być oznaczona jako abstrakcyjna - więcej o tym w załączonym artykule). Wtedy po jednej stronie jest "abstract", a po drugiej musi być "override" w języku C#.

PRZYKŁAD KODU ŹRÓDŁOWEGO

Spodziewaliście się tego, prawda :D? Mamy dwie klasy. Jedna dziedziczy od drugiej. Klasa bazowa posiada metodę, która działa w sposób domyślny i taki będzie przekazywany "z pokolenia na pokolenie":

class MyBaseClass
{
	public void DoSomething()
	{
		Console.WriteLine("Standardowe działanie metody \"DoSomething\"");
	}
}

class MyChildClass : MyBaseClass
{
	
}

Przypuśćmy, że chcemy podstawić niestandardową implementację metody "DoSomething". No to mamy dwa wyjścia w "CSharpie": używając "override" w języku C# albo nie. Uwaga! Wybór wpływa na późniejsze działanie!

PRZESŁANIANIE BEZ SŁOWA "OVERRIDE"

Przesłanianie metody może odbyć się bez "prawdziwego" przesłaniania, a raczej zastępowania nową wersją porzucając starą. Było o tym sposobie napomknięcie w artykule na temat zastosowań słowa kluczowego "new", a konkretnie chodzi o to:

class MyBaseClass
{
	public void DoSomething()
	{
		Console.WriteLine("Wykonuję instrukcje klasy bazowej.");
	}
}

class MyChildClass : MyBaseClass
{
	public new void DoSomething()
	{
		Console.WriteLine("Wykonuję instrukcje klasy potomnej.");
	}
}

To przejdzie, tylko cały czas podkreślam, że to nada temu inne działanie. Kiedy stworzymy sobie zmienną typu "klasa potomna" i do drugiej typu "klasa bazowa" podstawimy referencję:

MyChildClass mcc = new MyChildClass();
MyBaseClass mbc = mcc;

to wówczas wywołanie metody z obu zmiennych:

mcc.DoSomething();	// przesłonięta wersja metody w klasie potomnej
mbc.DoSomething();	// bazowa wersja metody w klasie bazowej

sprawi, że będzie obowiązywać ta wersja, która znajduje się w klasie odpowiadającej typowi danych. W tym kontekście, "new" tak jakby wyznacza nowy początek wersji metody, która będzie przekazywana na kolejne klasy potomne. Gdybyście stworzyli następną klasę dziedziczącą od "MyChildClass" i w niej także przesłonilibyście tę samą metodę słowem "new", to nadal każda klasa będzie wykonywała swoją wersję:

MyChildChildClass mccc = new MyChildChildClass();
MyChildClass mcc = mccc;
MyBaseClass mbc = mccc;

mccc.DoSomething();	// przesłonięta wersja metody w klasie potomnej B
mcc.DoSomething();	// przesłonięta wersja metody w klasie potomnej A
mbc.DoSomething();	// bazowa wersja metody w klasie bazowej

i analogicznie, brak zdefiniowania nowej wersji sprawi, że wywołanie od klasy "MyChildChildClass" zostanie "zapożyczone" od klasy bazowej tej klasy potomnej ("MyChildClass"). Technika przesłaniania bez używania "override" w języku C# nazywa się wiązaniem statycznym i polega na uwzględnianiu deklarowanego typu obiektu.

Nie można zastosować tej metody w stosunku do właściwości!

Przesłanianie metody w języku C# bez uzycia słowa kluczowego "override"

Przesłanianie w języku C# po zastosowaniu słowa kluczowego "new" nazywa się "wiązaniem statycznym". To spowoduje uwzględnienie odpowiedniej wersji metody w zależności od typu danych zmiennej. Ta technika nie zadziała na właściwościach!

PRZESŁANIANIE ZE SŁOWEM "OVERRIDE"

Co innego jak skorzystacie z kombinacji słów "virtual" oraz "override" w języku C#. Wtedy będzie to wiązanie dynamiczne, czyli uwzględnianie faktycznego typu obiektu na jaki wskazuje zmienna. "virtual" ląduje zaraz po modyfikatorze dostępu, w klasie bazowej, a "override" w klasie potomnej, też po modyfikatorze dostępu:

class MyBaseClass
{
	public virtual void DoSomething()
	{
		Console.WriteLine("Wykonuję instrukcje klasy bazowej.");
	}
}

class MyChildClass : MyBaseClass
{
	public override void DoSomething()
	{
		Console.WriteLine("Wykonuję instrukcje klasy potomnej.");
	}
}

Wtedy zostanie wykonana wersja przesłonięta, niezależnie od typu danych!

MyChildClass mcc = new MyChildClass();
MyBaseClass mbc = mcc;

mcc.DoSomething();	// przesłonięta wersja metody w klasie potomnej
mbc.DoSomething();	// przesłonięta wersja metody w klasie potomnej

Co się tyczy właściwości, możemy użyć tej techniki, żeby przesłonić standardowe przyjmowanie bądź przypisywanie wartości. Jeżeli właściwość jest wirtualna:

class MyBaseClass
{
	public virtual int X
	{
		get
		{
			return 15;
		}
	}
}

to klasa bazowa ma w sobie implementację i przesłanianie w klasie potomnej przy użyciu "override" w języku C# jest opcjonalne:

class MyChildClass : MyBaseClass
{
	public override int X
	{
		get
		{
			return 38;
		}
	}
}

Natomiast kiedy jest abstrakcyjna:

abstract class MyBaseClass
{
	public abstract int X {get;}
}

ustalamy tylko czy ma mieć akcesor, mutator, czy jedno i drugie, a W KAŻDEJ klasie potomnej musimy przesłonić i nałożyć implementację:

class MyChildClass : MyBaseClass
{
	public override int X
	{
		get
		{
			return 38;
		}
	}
}

ODWOŁANIE SIĘ DO BAZOWEJ WERSJI METODY

Na końcówkę przypomnę o słówku "base" w języku C#, za pomocą którego możemy odwołać się do bazowej wersji metody, bez względu na okoliczności. Ono także ma związek z niniejszym tematem, gdyż stosując przesłanianie pierwszym lub drugim sposobem, możemy wywołać "bazową" wersję metody o tej samej nazwie lub każdej innej (o ile posiada wewnętrzny, publiczny lub chroniony modyfikator):

public override void DoSomething()
{
	base.DoSomething();
	Console.WriteLine("Wykonuję instrukcje klasy potomnej.");
}
Słowo kluczowe "override" w języku C# jako przesłanianie metody

"override" tyczy się przesłaniania pierwotnej "wersji" metody albo właściwości klasy bazowej. Fachowo ta technika nazywa się "wiązaniem dynamicznym". Jeżeli metoda albo właściwość jest abstrakcyjna, wtedy przesłonięcie w klasie potomnej jest obowiązkowe!

Słowo kluczowe "override" w języku C# jako przesłanianie właściwości

Etap przesłaniania dobiegł końca. Rozumiem, że przesłanianie przy pomocy słów "new" oraz "override" w języku C# może sprawić, że "czacha dymi" :P, jednak to również zaliczyłbym do tematów podstawowych z programowania w "CSharpie" świadczących o Waszej samodzielności.

PODOBNE ARTYKUŁY