Ich möchte die Gründe dafür wissen, warum zwei verschiedene Klassen verwendet werden, anstatt nur Klasse für beide zu verwenden.
Die kurze Antwort lautet: "Ihre Annahme, dass Klassen Instanzen einer systemweiten Klasse sind, ist falsch, jede Klasse ist tatsächlich eine Instanz einer klassenspezifischen Metaklasse" und auch "es würde nicht anders funktionieren".
Eine kleine Änderung an der Antwort ist: "Die Namen sind wirklich verwirrend, es ist manchmal einfacher, sich einfach ihre Rollen einzuprägen und nicht zu viel darüber nachzudenken, wie sie funktionieren."
Kurze haarige Antwort:
Metaklasse ist eine Instanz, genau wie alle anderen gewöhnlichen Smalltalk-Klassen, und erfordert eine eigene Klasse. Jede Instanz eines regulären Smalltalk-Objekts hat eine Klasse, deren Vererbung der Klassenhierarchie folgt. Jede Klasse ist selbst eine Instanz einer klassenspezifischen Metaklasse, wobei die Vererbung der Metaklassenhierarchie folgt. Jede Metaklasse ist selbst eine Instanz der Klasse Metaclass, die von der virtuellen Maschine in einem kleinen Trick kurzgeschlossen wird, da niemand einen Nutzen daraus gezogen hat, der Klasse Metaclass ein Elternteil zu geben, und alle, die es versucht haben, haben das im Allgemeinen gefunden Ihre geistige Gesundheit begann dabei zu schwinden.
Länger, immer noch haarige Antwort:
Smalltalk ermöglicht, dass jede Klasse klassenspezifische Nachrichten enthält. Diese entsprechen in etwa den statischen Methoden in Java - allerdings mit einigen signifikanten Unterschieden. Einer dieser Unterschiede besteht darin, dass Smalltalk-Klassen tatsächlich instanziierte Objekte sind - sie sind Live-Objekte im System, komplett mit der Fähigkeit, von anderen Objekten zu erben und Instanzvariablen zu enthalten.
Diese Eigenschaft führt zu einer möglichen Vielzahl von Vererbungshierarchien im System. Reguläre Objekte sind jeweils Instanzen genau einer Klasse, wobei die Nachricht an ein Objekt gesendet wird, das die Klasse der Objekte durchsucht, und dann die Vererbungskette der Klassenhierarchie verfolgt. Nachrichten, die an reguläre Objekte gesendet werden, werden in der Klassenhierarchie aufgelöst.
Klassenobjekte sind auch Instanzen einer klassenspezifischen Metaklasse. Nachrichten, die an ein Klassenobjekt gesendet werden, werden durch Suchen in der klassenspezifischen Metaklasse und dann in der Metaklassenhierarchie aufgelöst.
Up einer weiteren Schicht, Metaklassenobjekte sind jeweils Instanzen einer systemweit eindeutigen Metaklassenklasse. Nachrichten, die an ein Metaklassenobjekt gesendet werden, werden in der systemweit eindeutigen Metaklasse nachgeschlagen, die nicht von irgendjemandem erben darf und als Kurzschluss in der VM fest verdrahtet ist.
Technisch hat das System zwei Vererbungshierarchien und eine dritte, die mit einem Kurzschluss gefälscht ist. Es gibt keinen theoretischen Grund, um zwei zu stoppen, obwohl es viele praktische gibt. Dadurch kann jedes Objekt eigene, objektspezifische Nachrichten, Nachrichten, jede Klasse eigene, eindeutige Klassennachrichten und Nachrichten haben und alle Metaklassen dazu zwingen, nur auf einen Satz von Nachrichten zu antworten, die in der Metaklasse definiert sind.
Ordentlich, nicht wahr?
Sie benötigen eindeutig zwei ClassDescriptions für eine Klasse: eine für die Instanzmethoden und eine für die Klassenmethoden.
Nun könnten Sie immer noch versuchen, Class für beide Objekte zu verwenden. Ich denke, ein Grund für Metaclass ist, dass Sie die beiden unterscheiden müssen. Wenn Sie sich die Methoden theMetaClass
und theNonMetaClass
ansehen, sehen Sie, dass sie sich gegenseitig spiegeln: Sie gehen von Metaklasse zu Klasse durch dieses Klassenmitglied und von Klasse zu Metaklasse durch den regulären Klassenzeiger (den jedes Objekt besitzt). Wenn beide von der Instanz Klasse waren, konnten sie nicht wissen, welche Seite sie implementieren - es sei denn, es gab einen Flag-Slot, was schlimmer ist als das Erstellen von Unterklassen.
Das ist eines dieser Dinge, die ich perfekt verstehe ... bis ich es erklären muss ;-) Nach viel Destillation ...
Gegeben:
Daher sollten Klassen und Instanzen unterschiedliche Verhaltens-Spezifizierer (d. h. Klassen) haben.
Anders ausgedrückt, was wir "Instanzseite" nennen, repräsentiert die Instanzseite der Klasse . Was wir "Klassenseite" nennen, repräsentiert die Instanzseite der Metaklasse .
Class definiert zum Beispiel #addClassVarNamed: und #addInstVarNamed :, da beide auf der Instanzseite sinnvoll sind, wobei Metaclass nur #addInstVarNamed: definiert, da es keine Klassenseiten-Klassenvariablen gibt.
Um mehr über die Einzelheiten zu erfahren, siehe "Pharo By Example" oder "Fundamentals of Smalltalk Programming Technique"