?
Ja, Sichtbarkeit auf "class" Ebene ist ein Punkt den ich meine. Es geht mir dabei aber eher um die Einfachheit.
Stell dir einfach mal vor, du hast eine Sprache, die ist ähnlich wie C++, nur dass sie OOP nicht unterstützt. Das Schlüsselwort Class gibt es nicht. Du möchtest dieser Sprache nun Unterstützung für OOP bieten. Smalltalk kennst du nicht, genauso wie jede andere Programmiersprache mit Unterstützung für OOP.
- Du möchtest Daten zu einem Paket verschnüren und diesem Paket ein paar Funktionen zuweisen, die zusammen einen Objekttyp bilden. Du möchtest von diesem Objekttyp Instanzen, also Objekte erstellen.
In dynamisch typisierten Programmiersprachen stehst du jetzt vor einem Problem, da genau dies die Stärke von umfangreichen Typensystem ist. Man könnte, oder müsste sich hier bereits dazu entschließen ein neues Konstrukt zu erlauben: Die Klasse. Um effizient auf die Methoden einer Klasse zugreifen zu können, werden diese in den Objekten referenziert. Passende Syntax dazu:
My_Car.Speed = 4.0;
My_Car.Accelerate;
// das Datenfeld Accelerate ist eine Referenz auf die Methode Accelerate
Was ist aber in C++? Man hat typedef, man hat struct und man kann Funktionen überladen. Du erstellst Einen structtyp für die Daten und ein paar Funktionen, die diesen structtyp als Parameter entgegennehmen, wodurch sie daran gebunden werden. Passende Syntax:
My_Car.Speed = 4.0;
Accelerate(My_Car);
// My_Car hat kein Datenfeld Accelerate, es gibt die lose Funktion
// Accelerate, die My_Car entgegen nehmen kann. Man erhält Bindung
// über das Typensystem.
- Du möchtest weitere Objekttypen erstellen, die ihre Eigenschaften von bereits vorhandenen Objekttypen erben. Diese erbenden Typen sollen neue Datenfelder und neue Funktionen erlauben, sowie das Überladen von Funktionen.
Wieder muss man in dynamisch typisierten Programmiersprachen auf dieses neue "Klassen"-Konstrukt zugreifen, in C++ aber nicht. Typenvererbung ist möglich, neue Datenfelder kann man auch ohne neue Konstrukte ermöglichen. Man nutzt vorhandene Syntax aus typedef, Typenvererbung und struct. Neue Funktionen für diese erbenden Typen erstellt man, indem man Funktionen schreibt, die den erbenden Typ als Parameter erwarten. Das Überladen ist ebenfalls bereits durch das Typensystem möglich
- Du möchtest in der Sprache dynamisch zu den Funktionen eines Objekttyps springen können, um Konstrukte zu erlauben, bei denen zur Übersetzungszeit nicht klar ist, welchen Typ einer Typenhierarchie du gerade vor dir hast - Polymorphie.
Benötigt man hier wirklich neue Syntax? Vielleicht ja, das ist Geschmackssache. Vielleicht möchte man Typen haben, wo das erlaubt ist, andere wo das nicht erlaubt ist. Man könnte das dispatchen erlauben, indem man bei Variablendeklaration anweist, dass diese Variable nicht nur den Typ aufnehmen kann, den man angibt, sondern auch seine Nachkommen:
Class Vehicle My_Car;
// Das Objekt My_Car wird deklariert, es ist vom Typ "Class Vehicle",
// also von "Vehicle" und seinen Nachkommen
- Natürlich soll die Sichtbarkeit der Elemente deiner Klasse gesteuert werden können
Ist das wirklich Aufgabe deines Typensystems? Selbst in C hast du bereits einen "public" Bereich (den header) und einen "private" Bereich (den body). Man könnte doch das Modulsystem weiter für diese Aufgabe nutzen und im header einen Protected-Block erlauben, womit die Sichtbarkeit geregelt wäre. Wieder ohne, dass man ein vollkommen neues Konstrukt benötigt und auch ohne Redundanz indem du Sichtbarkeit alleine auf Modulebene und nicht auch auf Klassenebene regelst.
Alles zusammen wundere ich mich, warum statisch typisierte Programmiersprachen sich so stark an die Syntax von Smalltalk orientieren, wo doch die Probleme bei dem Design der OOP-Unterstützung vollkommen andere sind. Bei dynamischen Systemen musst du Kontrolle erschaffen, die in umfangreichen Typensystemen bereits vorhanden ist, bei statischen Systemen musst du dynamisches Verhalten dort bieten, wo man per Design eigentlich keines hat.