Zugriffsmodifikator
Zugriffsmodifikatoren (engl. access specifier, access modifier oder kurz modifier) sind Schlüsselwörter in Programmiersprachen, die den Grad definieren, in dem Teile eines Programms auf andere Teile eines Programms (wie beispielsweise Variablen, Funktionen oder Klassen) zugreifen können. Sie regeln die Sichtbarkeit dieser Teile innerhalb eines Programms.[1][2][3][4]
Große Verbreitung finden sie nur in objektorientierten Sprachen, wenngleich es einige von ihnen auch in funktionalen Programmiersprachen gibt.
Static in funktionaler Programmierung
Der einzige übliche Zugriffsmodifikator in funktionalen Programmiersprachen ist static
(allerdings nur in einer von vier Bedeutungen). Die Zugriffseinschränkung geschieht dabei über den Linker, nicht den Compiler, und wird meist zur Verhinderung des dateiübergreifenden Verwendens einer Variable eingesetzt. In den übrigen drei Bedeutungen fungiert static
nicht als Zugriffseinschränkung.
Zugriffsmodifikatoren in objektorientierten Programmiersprachen
In objektorientierten Programmiersprachen wird von Zugriffsmodifizierern im Allgemeinen sehr umfangreich Gebrauch gemacht. Sie stellen zugleich das Herzstück des Kapselungskonzeptes dar. Ihre Einhaltung wird durch den Compiler überwacht. Einen vollständigen Schutz im Sinne eines Schutzes vor böswilligen Angriffen bieten sie dabei aber nicht, etwa ist es möglich in Sprachen, die Zeiger erlauben, mit relativ geringem Aufwand diese Beschränkungen zu umgehen. Vielmehr dienen sie dazu, die Wartung zu vereinfachen und die Nachvollziehbarkeit und Wiederverwendbarkeit von Code (etwa wenn die Funktionalität erweitert oder angepasst werden muss) für den Programmierer zu gewährleisten. Die Beschränkungen hängen dabei im Allgemeinen davon ab, wie die Klasse des Aufrufers mit der Klasse des aufzurufenden Members verwandt ist.
In objektorientierten Programmiersprachen sind folgende Zugriffsmodifikatoren üblich:
Zugriff möglich für | Verwendung | Typische Schreibweisen |
---|---|---|
Alle Klassen | Funktionalitäten, die die Klasse bereitstellen soll (Klasseninterface) | public (C++, Java, C#), Public (VB.Net) |
Nur Erben | Funktionalitäten, auf die der Programmierer zugreifen muss oder die der Programmierer ändern muss, wenn er die Funktionalität der Klasse gemäß dem Vererbungskonzept erweitern möchte. | protected (C++, Java, C#), Protected (VB.Net), manchmal auch family |
Nur klassenintern | Funktionalitäten, die gemäß dem Prinzip der Kapselung nach außen hin nicht bekannt sein müssen. | private (C++, Java, C#), Private (VB.Net) |
Daneben gibt es noch Zugriffsmodifizierer, die außerhalb des Vererbungskonzeptes arbeiten. Ihre Verwendung ist in Ausnahmefällen sinnvoll, gilt aber häufig als schlechter Programmierstil oder als Indikator für ein schlechtes Programmdesign. Hierzu zählen folgende Modifizierer:
Zugriff möglich für | Verwendung | Typische Schreibweisen |
---|---|---|
Klassen aus demselben Paket/derselben Assembly | Nur Sonderfälle: Die gesamte DLL hat Zugriff auf die Methode. Programme, die die DLL verwenden wollen, haben hingegen keinen Zugriff. | ohne Schlüsselwort (Java), internal (C#), Friend (VB.Net), manchmal auch assembly |
Eine bestimmte Klasse auf alle Klassenmember | Nur Sonderfälle: friend [Klasse] macht [Klasse] befreundet, dies bedeutet, dass [Klasse] Zugriff auf alle (auch private) Member einer Klasse hat (Friend-Funktion) | (nur in C++) |
static
ist im Gegensatz zur funktionalen Programmierung in der objektorientierten Programmierung kein Zugriffsmodifizierer, sondern ein Speichermodifikator (siehe: static (Schlüsselwort)#static und Shared bei Klassenmembern).
Zugriffsmodifizierer können häufig nicht kombiniert werden, da dies meist nicht sinnvoll ist. Wo dies jedoch sinnvoll ist, kann es hingegen Ausnahmen geben. In C# und VB.Net können beispielsweise der protected
und der internal
-Modifizierer kombiniert werden, damit sowohl Erben außerhalb der Assembly als auch Klassen in derselben Assembly, die nicht von derselben Klasse erben, auf einen Member zugreifen können.
In den meisten Programmiersprachen werden Zugriffsmodifizierer direkt in der Deklaration des Members angegeben. Eine Ausnahme bildet C++, wo Funktionen mit gleichen Zugriffsmodifizierern blockweise gruppiert werden, wobei diese Blöcke dann einen gemeinsamen Zugriffsmodifizierer haben. Diese Blöcke werden dann dementsprechend mit public:
, protected:
oder private:
eingeleitet.
Sprachspezifische Besonderheiten
In Java kann z. B. eine Codedatei beliebig viele Klassen enthalten, davon darf aber nur eine public sein. Für den Nutzer der Datei ist nur diese eine Klasse sichtbar und somit nutzbar. Mehrere öffentlich sichtbare Klassen müssen hingegen auch mehrere Dateien verwenden.
In C++ erlaubt das friend-Schlüsselwort anderen Klassen, auf private Member zuzugreifen.
Beispiel in C++
//Header:
class AnotherClass;
class C
{
friend AnotherClass;
public:
int i;
float k;
int m;
protected:
int s;
private:
int p;
};
class D : public C
{
//Klasse kann auf i, k, m und s zugreifen.
//Klasse kann nicht auf p zugreifen.
};
class E
{
//Klasse kann auf i, k und m zugreifen.
//Klasse kann nicht auf s und p zugreifen.
};
class AnotherClass
{
//Klasse kann auf i, k, m, s und p zugreifen.
};
Beispiel in C#
public class Class1
{
//Arten der Anwendung auf Methoden:
public void MethodPu() {/*...*/}
protected int PropertyPr {get; private set;}
internal void MethodInt() {/*...*/}
protected internal void MethodPrInt() {/*...*/}
private void MethodPri() {/*...*/}
//Anwendung des Schlüsselwortes auf Klassen:
private class Subclass : SubclassVorlage
{
public int Test {get; set;}
public overrides int GetNumber() {return 3;}
void Example()
{
//Zugriff auf alle Member von Class1, sowie auf Subclass und Subclass. Test möglich.
}
}
public SubclassVorlage GetNewSubClass() {return new Subclass();}
//public Subclass GetSubClassDirekt() //Kompilierfehler: Unzulässiger Rückgabewert: Methode ist public, Subclass ist aber private.
private Subclass GetSubClassDirekt2() {return new Subclass();} //Methode als private allerdings möglich.
public SubclassVorlage GetNewSubClass2() {return GetSubClassDirekt2();} //Zulässig, nur Rückgabe-/Übergabewerte
// Müssen gleiche oder höhere Zugriffsrechte haben, der Code der Methode darf auch private Methoden verwenden.
//Auswirkungen der Anwendung des Schlüsselwortes auf Methoden in derselben Klasse:
public void Example()
{
//Zugriff auf alle Member von Class1, sowie auf Subclass und Subclass. Test möglich
}
}
public class SubclassVorlage
{
public virtual int GetNumber() {return 2;}
}
public class ClassInherit : Class1
{
//Auswirkungen der Anwendung des Schlüsselwortes auf Methoden in einer erbenden Klasse:
public void Example()
{
this.MethodPu(); //Zugriff möglich
int v = this.PropertyPr; //Getter möglich
//this.PropertyPr = v + 1; //Zugriff auf privaten Setter nicht möglich
this.MethodInt(); //Zugriff auf interne Methode nur möglich, wenn in derselben DLL programmiert.
this.MethodPrInt(); //Zugriff auf protected-Member innerhalb und außerhalb der DLL möglich
//this.MethodPri(); //Zugriff auf private Methode nicht möglich.
//Class1.Subclass c = new Class1.Subclass(); //Zugriff auf private Subklasse nicht möglich, da der
// Klasseninhalt nur für Class1 bekannt ist, daher auch Zugriff auf Class1.Test(); nicht möglich.
SubclassVorlage w = this.GetNewSubClass(); //Sichtbarkeit der Basisklasse von Class1.Subclass gegeben.
int x = w.GetNumber(); //Resultat: 3: Eingeschränkte Sichtbarkeit hat keinen Einfluss auf Vererbungskonzept.
}
}
public class ClassNotInherit
{
//Auswirkungen der Anwendung des Schlüsselwortes auf Methoden in einer unbeteiligten Klasse:
public void Example()
{
this.MethodPu(); //Zugriff möglich
//int v = this.PropertyPr; //Zugriff nicht möglich, da die Klasse kein Erbe ist.
this.MethodInt(); //Zugriff auf interne Methode nur möglich, wenn in derselben DLL programmiert.
this.MethodPrInt(); //Zugriff nur in derselben DLL, da die Klasse kein Erbe ist.
//Class1.Subclass c = new Class1.Subclass(); //Zugriff auf private Subklasse nicht möglich.
}
}
Siehe auch
- Zugriffsfunktion – erlaubt das Lesen und Schreiben von sonst nicht erreichbaren Membern auch von außerhalb.
- Datenkapselung (Programmierung)