Das Folgende ist Pseudocode, ich habe es in Java und PHP ausprobiert und beide haben funktioniert:
class Test {
private int a = 5;
public static function do_test(){
var t = new Test();
t.a = 1;
print t.a // 1
}
}
Test::do_test();
Warum können Sie dies im OOP-Paradigma tun und wozu dient es?
equals
dass private Felder einer anderen Instanz überprüft werden müssen. (Posting als Kommentar, da dies kurz ist, und nichts über die OOP-Ness dieses Ansatzes)this
, sodass die einzigen Objekte ihrer eigenen Klasse die sind, die sie selbst erstellen (oder die als Parameter übergeben werden). Wenn Sie dies als eine Verletzung der Kapselung oder einer Sicherheitslücke betrachten, ist es nicht so, als wäre es eine sehr große Lücke und es lohnt sich möglicherweise nicht, sie zu schließen.Antworten:
In Java sind private Variablen für die gesamte Klasse sichtbar. Auf sie kann über statische Methoden und über andere Instanzen derselben Klasse zugegriffen werden.
Dies ist zum Beispiel bei Factory-Methoden nützlich . Eine Factory-Methode initialisiert normalerweise ein Objekt, das so komplex ist, dass Sie es nicht dem Anwendungscode überlassen möchten. Für die Initialisierung benötigt die Factory-Methode häufig Zugriff auf die Klasseninternale, die Sie nicht verfügbar machen möchten. Der direkte Zugriff auf die privaten Variablen erleichtert Ihnen das Leben erheblich.
Wenn Sie jedoch die Implementierungsdetails einer Klasse auch vor statischen Methoden oder vor anderen Instanzen dieser Klasse verbergen möchten, können Sie dem Datenmuster für private Klassen folgen . Fügen Sie alle privaten Variablen einer Klasse in eine private innere Klasse ein und delegieren Sie alle Getter oder Setter an Getter und Setter dieser inneren Klasse.
Eine andere Möglichkeit besteht darin, eine Schnittstelle für die Klasse zu definieren, die alle öffentlichen Methoden der Klasse deklariert und dann, wo immer möglich, nur auf die Klasse unter dieser Schnittstelle verweist. Ein Verweis auf den Schnittstellentyp kann nicht verwendet werden, um direkt auf etwas zuzugreifen, das nicht in der Schnittstelle deklariert ist, egal wo (außer natürlich mit Reflektion). Wenn Sie eine objektorientierte Programmiersprache verwenden, die keine Schnittstellen hat (wie z. B. C ++), können Sie diese mit einer abstrakten Basisklasse simulieren, die von der eigentlichen Klasse geerbt wird.
quelle
Einige Sprachen und Laufzeit-Frameworks (z. B. Java, .NET) gehen davon aus, dass jedem, der den Code für eine bestimmte Klasse kompiliert, vertraut werden kann, dass er keine privaten Member einer Instanz dieser Klasse auf eine Weise verwendet, die sich nachteilig auf deren Richtigkeit auswirkt Operation. Andere Sprachen und Frameworks sind in dieser Hinsicht restriktiver und erlauben keinen Zugriff auf private Mitglieder einer Instanz, außer durch Code, der auf dieser Instanz ausgeführt wird . Beide Ausführungen haben Vor- und Nachteile.
Der größte Vorteil, den Code innerhalb einer Klasse auf private Mitglieder einer Instanz zugreifen zu lassen, besteht darin, dass es Fälle gibt, in denen diese Zugriffsebene angemessen ist. Wenn Sie auf
private
diese Weise arbeiten, ist es nicht mehr erforderlich, entweder ein anderes Zugriffsqualifikationsmerkmal für diesen Zweck verfügbar zu haben oder sonst wird der Code gezwungen, Mitglieder breiter darzustellen, als dies ansonsten ideal wäre.Ein Vorteil des Nichtzulassens eines solchen Zugriffs (wie dies im Microsoft Common Object Model (COM) der Fall war) besteht darin, dass externer Code Klassen als Schnittstellen behandeln kann. Wenn eine Klasse
ImmutableMatrix
ein privates oder geschütztes enthältdouble[][]
dahinter liegendes Feld, und wenn der Code innerhalb der Klasse den Trägers Reihe von anderen Fällen untersucht, dann wird es nicht möglich sein , eine nicht-Array-backed - Klasse zu definieren (zBZeroMatrix
,IdentityMatrix
) , die als könnte außerhalb Code verwenden einImmutable2dMatrix
, ohne dass diese Klasse das Hintergrundfeld mit einbeziehen muss. Wenn nichts inImmutable2dMatrix
verwendet private Mitglieder einer anderen Instanz alsthis
, dann wäre es möglich, die Klasse umzubenennenImmutableArrayBackedMatrix
und eine neue abstrakteImmutableMatrix
Klasse zu definieren, dieImmutableArrayBackedMatrix
als Subtypen auch die oben genannten Klassen ohne Array-Unterstützung haben könnte.Beachten Sie, dass ein solches Refactoring nicht dadurch verhindert werden würde, dass die Sprache "erlauben" würde
ImmutableMatrix
, das Backing-Array auf andere Instanzen als zu untersuchenthis
, es sei denn, die Sprache nutzte diese Fähigkeit und untersuchte tatsächlich externe Instanzen. Der primäre Effekt der Einschränkung einer solchen Verwendung durch eine Sprache besteht darin, dass der Compiler bei jedem Versuch, Code zu schreiben, der für ein solches Refactoring nicht zugänglich wäre, sofort quietscht.quelle
Java ist keine objektorientierte Sprache, sondern eine klassenbasierte Sprache. Die Klasse bestimmt die Operationen und den Verhaltenszugriff und nicht die Instanz.
Seien Sie also nicht allzu überrascht, dass Sie damit Dinge tun können, die nicht streng objektorientiert sind.
Da sich die Methode im selben Klassenbereich wie die Instanz befindet, hat sie vollen Zugriff auf private Mitglieder. Ähnliche Regeln gelten für Instanzen innerer Klassen, die auf Daten aus Instanzen äußerer Klassen zugreifen. Eine Instanz einer inneren Klasse kann auf private Mitglieder der äußeren Klasse zugreifen.
Dies wird von C ++ geerbt, wo es nützlich ist, um Konstruktoren zum Kopieren und Verschieben zu erstellen. Es ist auch nützlich, um zwei Objekte zu vergleichen oder zu kombinieren, deren Wert von Elementen abhängt, auf die nicht auf effiziente Weise öffentlich zugegriffen werden kann (z. B. sollte der Getter für ein Array in Java das Array kopieren, damit der Client-Code es nicht ändern kann und sich ändert der interne Zustand des Objekts, aber das Kopieren von Arrays zum Vergleich der Objektgleichheit ist nicht effizient)
quelle