OK, hoffentlich ist dies eine subjektive Frage für Programmierer, aber hier geht es weiter. Ich erweitere ständig meine Kenntnisse in Sprachen und Software-Engineering-Praktiken ... und bin auf etwas gestoßen, das für mich überhaupt keinen Sinn ergibt.
In C ++ enthalten Klassendeklarationen private:
Methoden und Parameter in der Header-Datei, die Sie theoretisch an den Benutzer übergeben, um sie einzuschließen, wenn Sie sie zu einer Bibliothek machen.
In Objective-C machen @interface
s fast dasselbe und zwingen Sie dazu, Ihre privaten Mitglieder aufzulisten (zumindest gibt es eine Möglichkeit, private Methoden in die Implementierungsdatei aufzunehmen).
Nach allem, was ich sagen kann, können Sie mit Java und C # eine Schnittstelle / ein Protokoll bereitstellen, die alle öffentlich zugänglichen Eigenschaften / Methoden deklarieren und dem Codierer die Möglichkeit geben, alle Implementierungsdetails in der Implementierungsdatei auszublenden .
Warum? Die Kapselung ist eines der Hauptprinzipien von OOP. Warum fehlt C ++ und Obj-C diese grundlegende Fähigkeit? Gibt es eine Art Best-Practice-Workaround für Obj-C oder C ++, die die gesamte Implementierung verbirgt ?
Vielen Dank,
quelle
Antworten:
Die Frage ist, ob der Compiler wissen muss, wie groß ein Objekt ist. Wenn ja, muss der Compiler die privaten Mitglieder kennen, um sie hochzählen zu können.
In Java gibt es primitive Typen und Objekte, und alle Objekte werden separat zugewiesen, und die Variablen, die sie enthalten, sind wirklich Zeiger. Da ein Zeiger ein Objekt mit fester Größe ist, weiß der Compiler daher, wie groß eine Variable ist, ohne die tatsächliche Größe des Objekts zu kennen, auf das verwiesen wird. Der Konstruktor erledigt das alles.
In C ++ können Objekte lokal oder auf dem Heap dargestellt werden. Daher muss der Compiler wissen, wie groß ein Objekt ist, damit er eine lokale Variable oder ein Array zuordnen kann.
Manchmal ist es wünschenswert, die Klassenfunktionalität in eine öffentliche und eine private Schnittstelle zu unterteilen, und hier kommt die PIMPL-Technik (Pointer to IMPLementation) ins Spiel. Die Klasse verfügt über einen Zeiger auf eine private Implementierungsklasse, und die Methoden der öffentlichen Klasse können sie aufrufen Das.
quelle
Aufgrund des Designs von C ++ muss der Compiler wissen, wie groß das Objekt ist, um ein Objekt auf dem Stapel zu erstellen. Dazu müssen alle Felder in der Header-Datei vorhanden sein, da dies alles ist, was der Compiler sehen kann, wenn der Header enthalten ist.
Zum Beispiel, wenn Sie eine Klasse definieren
dann
sizeof(Foo)
istsizeof(a) + sizeof(b)
. Wenn es einen Mechanismus zum Trennen der privaten Felder gab, könnte der Header enthaltenmit
sizeof(Foo) = sizeof(a) + ???
.Wenn Sie private Daten wirklich verbergen möchten, versuchen Sie es mit der Pimpl-Sprache mit
im Header und eine Definition
FooImpl
nur fürFoo
die Implementierungsdatei in.quelle
Dies alles hängt von der Wahl des Designs ab.
Wenn Sie die privaten Implementierungsdetails der C ++ - oder Objective-C-Klasse wirklich ausblenden möchten, stellen Sie entweder eine oder mehrere von der Klasse unterstützte Schnittstellen bereit (reine virtuelle C ++ - Klasse, Objective-C @protocol) und / oder Sie erstellen die Klasse Sie können sich selbst konstruieren, indem Sie eine statische Factory-Methode oder ein Class Factory-Objekt bereitstellen.
Der Grund dafür, dass die privaten Variablen in der Header-Datei / Klassendeklaration / @ -Schnittstelle verfügbar gemacht werden, besteht darin, dass ein Verbraucher Ihrer Klasse möglicherweise eine neue Instanz davon erstellen muss und ein
new MyClass()
oder[[MyClass alloc]init]
im Client-Code den Compiler benötigt, um zu verstehen, wie groß eine MyClass ist Objekt ist, um die Zuordnung zu tun.Java und C # haben auch ihre privaten Variablen in der Klasse detailliert - sie sind keine Ausnahme, aber IMO ist das Schnittstellenparadigma bei diesen Sprachen viel häufiger. Möglicherweise verfügen Sie nicht in jedem Fall über den Quellcode, aber der kompilierte / Byte-Code enthält genügend Metadaten, um diese Informationen abzuleiten. Da C ++ und Objective-C diese Metadaten nicht haben, sind die einzigen Details die tatsächlichen Details der Klasse / @ -Schnittstelle. In der C ++ COM-Welt machen Sie die privaten Variablen keiner Klasse verfügbar, können jedoch die Header-Datei bereitstellen, da die Klasse rein virtuell ist. Ein Klassenfactory-Objekt wird registriert, um auch die tatsächlichen Instanzen zu erstellen, und es gibt einige Metadaten in verschiedenen Formen.
In C ++ und Objective-C ist das Verteilen der Header-Datei weniger aufwendig als das Schreiben und Verwalten einer zusätzlichen Schnittstelle / @ -Protokolldatei. Dies ist ein Grund, warum Sie die private Implementierung so oft sehen.
Ein weiterer Grund in C ++ sind Vorlagen. Der Compiler muss die Details der Klasse kennen, um eine Version dieser Klasse zu generieren, die auf die angegebenen Parameter spezialisiert ist. Die Größe der Mitglieder der Klasse hängt von der Parametrisierung ab, daher müssen diese Informationen vorhanden sein.
quelle