Jason. Cała informatyka w jednym miejscu!

Przechodzimy do kolejnego tematu będącego fragmentem wiedzy podstawowej na temat języka C#. Teraz mam Wam do przekazania parę akapitów opisujących czym są modyfikatory dostępu w języku C# i jak wpływają na widoczność wszelakiej maści konstrukcji. Zobaczcie koniecznie, nalegam :O! To jest elementarny wątek z którego będziecie później korzystać bez opamiętania!

MODYFIKATORY DOSTĘPU W JĘZYKU C# SKŁADAJĄ SIĘ Z PIĘCIU ODMIAN

Gotowi? To jedziemy. C# dysponuje pięcioma rodzajami określającymi poziom dostępu do danej składowej, metody, klasy, konstruktora klasy i wiele, wiele innych konstrukcji jakie zna ten język. Zrobimy następująco. Najpierw Wam przedstawię wszystkie dostępne kombinacje, a potem przejdziemy do tabelki, w której będzie ukazane które modyfikatory są dostępne dla jakiej konstrukcji. Nie spodziewajcie się pełnego zestawienia, skupimy się na tych najbardziej podstawowych, żeby zbyt daleko nie wchodzić w szczegóły. To w końcu ma być seria dla początkujących, abyście nie musieli wydawać dodatkowych pieniędzy na kształcenie się (pozdrawiam :D!).

ZNACZENIE MODYFIKATORA DOSTĘPU

Startujemy z tematem. Bywa prawie w każdym programie, że nie chcemy koniecznie udostępniać wszystkiego co zawiera w sobie dana klasa i mamy ochotę coś ukryć przed resztą świata. Właśnie po to służą modyfikatory dostępu w języku C#. Ich rola polega na ograniczeniu możliwości bezpośredniego odwoływania się do...w zasadzie czegokolwiek. Możemy je podstawić do klasy, możemy podstawić do metody, do struktury i do wielu innych konstrukcji.

Istnieją różne powody ukrywania bezpośrednich odwołań, natomiast w przeważającej części przypadków czyni się tak w celu zasłonięcia implementacji. Chodzi o utorowanie sobie możliwości przyszłościowych modyfikacji w kodzie tak, aby inny użytkownik mógł dalej z niego korzystać jak poprzednio, bez konieczności edytowania swojego kodu ani świadomości jak ta struktura w środku wygląda.

ZOBRAZOWANIE SYTUACJI

W ramach ekspresowego przykładu wyobraźmy sobie, że korzystamy z czyjejś klasy opisującej funkcję kwadratową (celem dużego uproszczenia, wyrzucamy szczegóły takie jak wykrywanie, czy "a" jest różne od zera). Załóżmy też, że taka "wersja 1.0" tej klasy udostępnia publiczną metodę służącą do zwrócenia wartości n-tego argumentu przy użyciu postaci ogólnej. Mogłoby to wyglądać tak:

public class QuadraticFunction
{
	private double a, b, c;
	
	public QuadraticFunction(double a, double b, double c)
	{
		this.a = a;
		this.b = b;
		this.c = c;
	}
	
	public double ValueOfNthArgument(double x)
	{
		return a*x*x + b*x + c;
	}
}

Wy natomiast moglibyście z niej skorzystać w taki sposób:

public class Program
{
	static void Main(string[] args)
	{
		QuadraticFunction qf = new QuadraticFunction(1.0, 5.0, 0.0);

		Console.WriteLine(qf.ValueOfNthArgument(3));
	}
}

Macie to ;)? Teraz wyobraźcie sobie, że ktoś wstawił aktualizację tej klasy i w chwili obecnej wygląda ona tak:

public class QuadraticFunction
{
	private double a, b, c, delta;
	
	public QuadraticFunction(double a, double b, double c)
	{
		this.a = a;
		this.b = b;
		this.c = c;
		delta = b*b - 4*a*c;
	}
	
	public double ValueOfNthArgument(double x)
	{
		double p = -b / 2*a;
		double q = -delta / 4*a;
		double difference = x - p;
		
		return a*difference*difference + q;
	}
}

Uległa zmianie implementacja metody wyliczającej wartość funkcji dla n-tego argumentu (postać kanoniczna funkcji kwadratowej)! Ale czy to znaczy, że trzeba modyfikować nasz kod? Nie :D! I właśnie o to chodzi! Nie trzeba będzie tego robić, dopóki nie zmieni się nazwa, parametry, bądź typ zwracanej wartości przez metodę, od której nasz kod źródłowy jest uzależniony. Gdybyśmy polegali na samych danych składowych (które siłą rzeczy musiałyby być otwarte), bylibyśmy zmuszeni do własnoręcznego modyfikowania kodu źródłowego i tym samym, narazilibyśmy się na powstawanie błędów i stratę czasu.

PIĘĆ RODZAJÓW MODYFIKATORÓW

Mamy opisane do czego to służy i dlaczego ma to sens. Poznajmy teraz typy. Modyfikatory dostępu w języku C# znane są pod pięcioma następującymi słowami kluczowymi (lub też kombinacjami słów kluczowych):

  1. public,
  2. private,
  3. protected,
  4. internal,
  5. protected internal.

Kolejność nie była sortowana pod jakikolwiek czynnik. Od razu przechodzę do wyjaśniania czym się różni każdy z wyżej wymienionych.

PUBLIC

Publiczny modyfikator dostępu kryjący się pod hasłem "public" oznacza przyznanie dostępu "na oścież". Każdy inny byt z każdego innego miejsca w kodzie może się odwołać bezpośrednio do tego, na co zostanie nałożony ten modyfikator. Modyfikator publiczny nie powinien być nakładany dla danych składowych (z wyżej opisanego powodu). Bardziej posłuży dla metod, właściwości, klas i ich konstruktorów. Najogólniej pisząc, powinno być publiczne tylko to, co na 100% będzie wykorzystywane na zewnątrz i nie ujawnia szczegółów implementacji:

KLASA "MYCLASS"
class MyClass
{
	public void DoSomething()
	{
			
	}
}
KLASA "PROGRAM"
class Program
{
	static void Main(string[] args)
	{
		MyClass mc = new MyClass();
		
		mc.DoSomething();
	}
}
PRIVATE

"private" to najbardziej restrykcyjny ze wszystkich modyfikatorów dostępu w języku C#. Nałożony na cokolwiek spowoduje, że to "coś" będzie dostępne wyłącznie dla samej konstrukcji wewnątrz. Dla reszty świata dostęp będzie zablokowany. Dosłownie. Ani kod zewnętrzny, ani klasa potomna, ani cokolwiek innego wystającego poza konstrukcję posiadającą coś prywatnego, nie ma prawa odwołać się do tego bezpośrednio.

Prywatny modyfikator dostępu jest najczęściej wykorzystywany w stosunku do danych składowych, aby nie zdradzały implementacji. Często stosuje się je także do samych metod, u których nie ma i nie będzie konieczności wykonywania ich instrukcji na zewnątrz:

KLASA "MYCLASS"
class MyClass
{
	private void DoSomething()
	{
			
	}
}
KLASA "PROGRAM"
class Program
{
	static void Main(string[] args)
	{
		MyClass mc = new MyClass();
		
		mc.DoSomething();	// błąd kompilacji, nie ma dostępu do metody z powodu prywatnego modyfikatora dostępu
	}
}
PROTECTED

Niniejszy modyfikator przeznaczony jest dla dziedziczenia przez klasy potomne. "protected", czyli chroniony, a konkretniej chroniony przed odwołaniami z zewnątrz, tak jak "private". Tyle tylko, że zwolnione są od tego wszystkie klasy potomne jakie dziedziczą od klasy bazowej posiadającej coś chronionego. Na tym polega cała różnica pomiędzy prywatnym, a chronionym modyfikatorem dostępu:

KLASA "MYBASECLASS"
class MyBaseClass
{
	protected int value;
}
KLASA "MYCHILDCLASS"
class MyChildClass : MyBaseClass
{
	public MyChildClass()
	{
		value = 15;	// dozwolone, klasa potomna uzyskuje dostęp do wszystkiego, co publiczne lub chronione
	}	
}
KLASA "PROGRAM"
class Program
{
	static void Main(string[] args)
	{
		MyChildClass mcc = new MyChildClass();

		mcc.value = 160;	// błąd kompilacji, nie ma dostępu do właściwości spoza hierarchii dziedziczenia
	}
}
INTERNAL

Są takie modyfikatory dostępu w języku C#, że uwzględniają programy składające się z wielu tzw. "zestawów" (gotowy program pod postacią pliku wykonywalnego, bądź biblioteki łączonej dynamicznie, DLL). Do tego wymyślono "internal" - modyfikator służący do określenia globalnego dostępu do czegoś, w obrębie jednego zestawu. Nie wchodząc w gigantyczne teorie, chodzi o zapewnienie publicznego dostępu dla danej konstrukcji, ale będzie ona widoczna tylko wtedy, gdy inny plik źródłowy pochodzi z tego samego zestawu. Zgodnie z treścią dokumentacji Microsoft na ten temat, jest to wysoce przydatne podczas programowania komponentowego. To już odbiega od podstaw języka jakie tu prezentuję.

PROTECTED INTERNAL

A na koniec, połączenie dwóch poprzednich opisanych modyfikatorów. "protected" + "internal" daje nam łącznie "protected internal". Modyfikator ograniczający widoczność czegoś nie tylko do tego samego zestawu, ale także do klas potomnych dziedziczących od klasy bazowej, która to coś posiada. Tyle :)!

KTÓRE MODYFIKATORY DOSTĘPU MOŻEMY WSTAWIĆ DO CZEGO?

Teraz druga część artykułu jakim jest przedstawienie tabelaryczne co gdzie można wstawić. Nie wszędzie każdy modyfikator zostanie przyjęty, dlatego też trzeba Was uprzedzić które chwyty są dozwolone:

public private protected internal protected internal
klasa zewnętrzna tak nie tak nie
struktura
interfejs
klasa zagnieżdżona tak
konstruktor klasy
dana składowa
właściwość (get, set)
metoda

Weźcie pod uwagę, że jeśli samemu nie nadacie jawnie modyfikatora dostępu, to zostanie przypisany odpowiedni domyślny. I tak:

Modyfikatory dostępu w języku C#

Modyfikatory dostępu w języku C# to pięć różnych stopni określania swobody dostępu do dowolnej konstrukcji, od pól przez klasy do interfejsów.


Jeszcze jeden "gigant" wśród artykułów za sobą! Zdaję sobie sprawę, że dla niektórych z Was może to działać odpychająco, jednak spróbujcie mi uwierzyć, że ciężko zawsze zachować kompromis pomiędzy wprowadzeniem w temat, a obszernością informacji dodatkowych. I ta pojawiająca się wątpliwość czy nie za wcześnie odkrywam pewne karty ;)...

PODOBNE ARTYKUŁY