Vor- und Nachteile der Strukturierung des gesamten Codes über Klassen und der Kompilierung in Klassen (wie Java)

13

Bearbeiten: Meine Sprache erlaubt im Gegensatz zu Java Mehrfachvererbung.

Ich habe begonnen, meine eigene Programmiersprache für Bildungs-, Freizeit- und potenziell nützliche Zwecke zu entwerfen und zu entwickeln.

Zuerst habe ich mich entschlossen, es auf Java aufzubauen.

Dies implizierte, dass der gesamte Code in Form von Klassen geschrieben und dieser Code in Klassen kompiliert wird, die von der VM geladen werden.

Ich habe jedoch Features wie Interfaces und abstrakte Klassen ausgeschlossen, da ich keine Notwendigkeit dafür gefunden habe. Sie schienen ein Paradigma durchzusetzen, und ich möchte, dass meine Sprache das nicht tut. Ich wollte die Klassen jedoch als Kompilierungseinheit behalten, da es praktisch erschien, sie zu implementieren, und mir gefiel die Idee einfach.

Dann bemerkte ich, dass ich im Grunde genommen ein Modulsystem habe, in dem Klassen entweder als "Namespaces" verwendet werden können, die Konstanten und Funktionen mithilfe der staticDirektive bereitstellen , oder als Vorlagen für Objekte, die instanziiert werden müssen ("tatsächlicher" Zweck von Klassen) in anderen Sprachen).

Jetzt frage ich mich: Was sind die Vor- und Nachteile von Klassen als Kompilierungseinheiten?

Außerdem wäre jeder allgemeine Kommentar zu meinem Design sehr dankbar. Ein informativer Beitrag zu meiner Sprache ist hier zu finden: http://www.yannbane.com/2012/12/kava.html .

jcora
quelle
1
Wenn die Klassen auch Namespaces enthalten, die alle Bezeichner in der Klasse eindeutig unterscheiden, verfügen Sie über eine vollständig eigenständige Kompilierungseinheit. Diese Klasse kann erfolgreich kompiliert werden, vorausgesetzt, alle Abhängigkeiten zu anderen Klassen können entweder durch Kompilieren oder durch Verweisen auf eine kompilierte Klasse in einer Assembly erfüllt werden. Eine solche Atomizität sollte offensichtliche Vorteile haben.
Robert Harvey
Randnotiz: Wenn Sie abstrakte Klassen und Interfaces entfernen, werden die Benutzer gezwungen , die Vererbung für Subtypisierung und Polymorphismus zu verwenden. Das muss schrecklichen Code produzieren. Außerdem ist es unglaublich eingeschränkt, es sei denn, Sie fügen Mehrfachvererbung hinzu (und behandeln die damit verbundenen Probleme).
1
@delnan: Eigentlich können Sie Composition immer noch verwenden, um Funktionen aufzubauen.
Robert Harvey
2
@RobertHarvey Ich nehme an, Sie sprechen von Einschränkungen durch fehlende Mehrfachvererbung. Ja, man kann es mit genügend Komposition emulieren, aber ich würde es kaum für akzeptabel halten. Beispielsweise müsste ein Objekt, das normalerweise zwei Schnittstellen implementiert, zweimal in Unterklassen unterschiedlicher Basisklassen implementiert werden (und obwohl beide Implementierungen an eine gemeinsame Klasse delegieren könnten, ist dies immer noch eine Unmenge an zusätzlichem Code, und Sie können es nicht einfach umdrehen eine Instanz von einem in eine Instanz des anderen).
@delnan: Was ist falsch daran, Vererbung für Subtypisierung und Polymorphismus zu verwenden? Das ist, was Vererbung ist für ...
Mason Wheeler

Antworten:

6

Was sind die Vorteile von Klassen als Kompilierungseinheiten?

Dies kann die Komplexität der Sprache verringern. Keine Notwendigkeit für unterschiedliche Konstrukte, alles wird gleich behandelt. In bestimmten Entwürfen (obwohl dies anscheinend nicht bei Ihnen der Fall ist) profitieren Sie davon, dass Sie keine Statik haben und dass Designprobleme auftreten (Probleme mit der Initialisierungsreihenfolge, Einschränkungen der Parallelität, Unbeholfenheit mit Generika / Typklassen). Es bietet auch einige Vorteile des Modulkonzepts, z. B. isolierte Modulinstanzen für Sandboxing oder Parallelisierung. und Modultypisierung, bei der Abhängigkeiten zu einer Schnittstelle passen und das gesamte zu implementierende Modul instanziiert und eingefügt werden kann.

Das Konzept hat jedoch tendenziell mehr Probleme als nicht. Realistisch gesehen können Sie nicht alles gleich behandeln, da Klassen der obersten Ebene spezielle Regeln benötigen, wie z. B. einen Standardkonstruktor (oder Sie stoßen auf seltsame Probleme, die sie zusammenfassen). Die Modularität von Kompilierungseinheiten wird auch sehr umständlich. Wie verweist eine Klasse überhaupt auf andere, wenn sie nur Klassen sind? Wie werden diese Abhängigkeiten behandelt und wie bestimmen Sie die richtige Reihenfolge für die Aufteilung der Klassen? Wie stellen Sie sicher, dass doppelte Klassenreferenzen von verschiedenen Teilen der App wiederverwendet werden (oder wie gehen Sie mit doppelten Instanzen um, wenn dies die gewünschte Semantik ist)?

Nachdem ich mich damit befasst hatte, stieß ich auf eine Reihe von Problemen mit Abhängigkeiten, der korrekten Festlegung von Gültigkeitsbereichen und Problemen mit der Initialisierung. Am Ende stoßen Sie auf Probleme, die "Klassen der obersten Ebene" zu etwas Besonderem machen, und auf viele Einschränkungen, damit sie funktionieren, die sie schließlich in einfache Namespaces umwandeln.

Telastyn
quelle
Ich plane nur eine einzige Klasse der obersten Ebene zu haben, die Object. Mir ist klar, dass ich wahrscheinlich ein besonderes Verhalten dafür brauchen werde, aber solange es ein Einzelfall ist, bin ich damit einverstanden. Ich glaube nicht, dass ich irgendwelche Abhängigkeitsprobleme haben werde. Es gibt eine Reihe von Klassen, die beim Starten der VM geladen werden. Einige von ihnen werden nativ implementiert (die System-Klasse), aber alle erben von Object. Sobald alles geladen wurde, lädt der KVM die Klasse, zu deren Laden er angewiesen wurde, und berechnet die Abhängigkeiten. Mich interessiert jedoch, welche Probleme die Statik mit sich bringt?
JCORA
@yannbane - Ich meine objectdamit nicht Klassen, die sich wie Module verhalten, sondern wie innere Klassen, die außerhalb ihrer Kompilierungseinheit nicht unbedingt öffentlich sind. "Berechnet die Abhängigkeiten" verwandelt sich in ein riesiges Hornissennest im Detail, wenn Sie ein Verhalten im DLL-Stil wünschen. ymmv. Wie für statische .
Telastyn
Dieses modulartige Verhalten würde durch die Verwendung statischer Methoden / Variablen erreicht, oder? Ist es schlecht, anstatt eine Klasse zu erstellen, die instanziiert werden kann, eine Klasse zu erstellen, die nur statische Member und Methoden enthält? Ich habe diesen Artikel gesehen, aber ich denke nicht, dass er für konstante statische Elemente oder statische Methoden gilt. Zum Beispiel sehe ich nichts falsches darin, eine MathKlasse zu erstellen , die eigentlich ein Modul mit statischen Methoden und einem konstanten statischen Doppelmitglied namens ist Pi.
Jcora
@yannbane - Nein, nicht wirklich. Module sind Module, weil sie instanziierbar sind. Ansonsten haben Sie nur C ++ - Namespaces. Wenn Sie Ihre Klassen der obersten Ebene auf Namespaces im C ++ - Stil beschränken, sind sie nicht mehr wirklich Klassen.
Telastyn 20.12.12
Hm, ich bin immer noch in Ordnung und sehe das Problem beim Erstellen von Modulen mit Klassen nicht wirklich. Und ja, Module fungieren als Namespaces, insbesondere Python-Module.
Jcora
4

Anstatt diese Frage zu beantworten, schlage ich vor, das MIT OpenCourseWare zu studieren , insbesondere 6.035 (Computer Language Engineering). Dies erklärt die ganze Problematik, so dass Sie nicht versucht werden, solche Fragen erneut zu stellen.

Computersprachenentwicklung

Einzige Voraussetzung ist Java.

http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-035-computer-language-engineering-spring-2010/lecture-notes/

Kursbeschreibung

In diesem Kurs werden Probleme im Zusammenhang mit der Implementierung übergeordneter Programmiersprachen analysiert. Zu den behandelten Themen gehören: Grundlegende Konzepte, Funktionen und Strukturen von Compilern, das Zusammenspiel von Theorie und Praxis sowie die Verwendung von Tools zum Erstellen von Software. Der Kurs beinhaltet ein Projekt für mehrere Personen zum Design und zur Implementierung von Compilern.

Mücke
quelle