W prawie wszystkich językach obiektowych istnieją tak zwane specyfikatory dostępu, przykładem których jest choćby public
czy private
. Pozwalają one ustalać, jak szeroko dostępne są poszczególne składniki klas w stosunku do reszty kodu. Modyfikatory te występują m.in. w trzech najpopularniejszych, kompilowalnych językach obiektowych: C++, C# i Javie.
Problem polega na tym, że w każdym z nich działają one inaczej. Mało tego: każdy z tych języków posiada inny zbiór tego rodzaju modyfikatorów. Dla kogoś, komu zdarza się pisać regularnie w przynajmniej dwóch spośród nich, może to być przyczyną pomyłek i nieporozumień.
Dlatego też przygotowałem prostą ściągawkę w postaci tabelki, którą prezentuję poniżej. Symbol języka występujący w komórce oznacza tutaj, że dany modyfikator (z wiersza) powoduje widoczność składnika klasy w określonym miejscu (z kolumny).
Specyfikator | Klasa | Podklasa | Pakiet | Reszta |
public |
C++ C# Java | C++ C# Java | C# Java | C++ C# Java |
protected |
C++ C# Java | C++ C# Java | Java | |
protected internal |
C# | C# | C# | |
internal |
C# Java | C# Java | ||
private |
C++ C# Java |
Parę uwag gwoli ścisłości:
public
, jako że w tym języku w ogóle nie istnieje pojęcie pakietu.internal
jest słowem specyficznym dla C#, a jego ekwiwalentem w Javie jest po prostu pominięcie modyfikatora w deklaracji (np. int x;
zamiast internal int x;
).protected internal
jest modyfikatorem występującym wyłącznie w C#/.NET.“Znaczek C++ nie występuje w kolumnie Pakiet nawet dla modyfikatora public, jako że w tym języku w ogóle nie istnieje pojęcie pakietu.”
Nie zgodzę się. W C++ mamy pojęcie jednostki kompilacji i “specyfikator” dla niej (static bądź namespace{}). Oczywiście ów “specyfikator” nie może dotyczyć metod klas, a jedynie zwykłych funkcji.
Nie jest to jednak pakiet w sensie Javy/.NET/Pythona/etc., bo nie jest:
– deklaratywny (wynika tylko z fizycznego umieszczenia pewnych elementów w danym pliku, a nie z jawnego napisania że X należy do pakietu Y)
– rozszerzalny
– hermetyzowalny w sensie OOP-u (jest tylko możliwość ukrycia elementów w static/namespace{} przez innymi jednostkami translacji; nie da się chociażby ukryć jakiegoś elementu przez resztą takiego “pakietu” ani mieć bardziej skomplikowanych przypadków jak te przedstawione wyżej)
A D? A gdzie jest D? ^^
Gdybyś i Ty zechciał wesprzeć Propagandę Lepszego Jutra i uzupełnić notkę, odpowiedni fragment specyfikacji jest tutaj, pod nagłówkiem “Protection attribute”:
http://www.digitalmars.com/d/1.0/attribute.html
W skrócie:
private – klasa, moduł
package – klasa, moduł, pakiet (vide ‘internal’)
protected – klasa, moduł, podklasa
public – klasa, podklasa, pakiet, reszta
(Jest jeszcze krok dalej od public, w postaci ‘export’ – z myślą o bibliotekach).
Uwagi na marginesie:
a) D ma moduły i pakiety, ale nie ma tam jak w Javie, że “1 moduł = 1 klasa publiczna”. Moduł może mieć cokolwiek: kilka klas, funkcje i zmienne globalne. Dlatego dodatkowo wyróżniamy widoczność w module (która nota bene istnieje zawsze :)).
b) “Zwykłe” zmienne i funkcje w module mogą również mieć atrybut private, package, public lub export; działanie j.w. Moduł generalnie w D przypomina w wielu miejscach klasę statyczną.
To ja w takim razie stanę w obronie Delphi, które tez jest przecież bardzo popularne, i nie wiem czy bardziej niż C# :D Też ma moduły, w każdym może być wiele klas, mogą one nawet być całe prywatne (widoczne tylko w danym module) gdy ich definicja jest w “implementation”. Public (oraz Published) i Protected są jak w javie. Private powoduje, że element jest widoczny w klasie i pakiecie (ale nie podklasach), czyli działa jak “internal”. Strict private działa jak jak private w javie czyli tylko w klasie widać. Strict protected działa jak protected z C# (czyli klasa i podklasa). Słowo “strict” przed “private” i “protected” powoduje, że elementy nie są widoczne w tym samym module, same “private” i “protected” powoduje, że są widoczne w module. Fioletowy dla Delphi w tabelce ? :D
Dzięki za uzupełnienia odnośnie innych języków. W tabelce zamieściłem te trzy głównie dlatego, że sam je dobrze znam/używam, a i – tak jak napisałem w notce – są to najpopularniejsze, kompilowalne języki obiektowe według TIOBE z października:
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Jak widać Delphi i D trzymają się tam dość kiepsko :) Oczywiście można dodać je do tabelki, ale wtedy jej rozmiary rozdęłyby się niepomiernie.
Może na świecie, ale wydaje mi się, że w Polsce Delphi ma się lepiej albo co najmniej tak samo jak C#. A tę notkę piszesz przecież po polsku, więc powinna być dla Polski sprofilowana ;)
Wg mnie powinno się dodać Delphi, w Polsce jest popularne bo dużo osób używa, ale też niepopularne bo Ci co nie piszą w nim nic o nim nie wiedza (o c++ ludzie wiedzą) co wynika z myśli “Delphi to jak Pascal). Sam fakt, że są klasy jest szokiem dla nich, a co dopiero fakt, że jest 5 zakresów widzialności (published to jak public). To byłby to szokujący post walczący z ciemnogrodem :D
Leciutko zboczę z tematu, ale w ogóle uważam, że ludzie nie używają Delphi bo sobie wmówili, że to z Pascala się wywodzi, a to nie jest “tru”, bo zamiast uroczych nawiasów klamrowych mamy jakieś długie begin…end i w ogóle kod taki rozwlekły. A następnie wracają do swojego ukochanego C++ i zaczynają się głowić, o czym myśleli tydzień temu tworząc taki oto warunek:
while(*a++=*b++);
Wbrew pozorom ta pętelka nie jest taka głupia, bo po dodaniu deklaracji zmiennych dostalibyśmy coś co działa identycznie jak pewna funkcja z biblioteki standardowej C :D
Ktoś ci każe w taki sposób pisać? Można zrobić normalnie wyglądającą pętlę, z czytelnym warunkiem i ciałem, albo jeszcze lepiej – użyć strcpy. Możliwość napisania nieczytelnego kodu to nie jest wada języka.
W Javie nie ma zdaje sie dostepu “internal” . Mozna go conajwyzej eumulowac.