Entwickler-Ecke

Programmierwerkzeuge - Klasse ableiten -> Editor soll Grundgerüst stellen


matze - Sa 23.08.08 20:12
Titel: Klasse ableiten -> Editor soll Grundgerüst stellen
Hallo.

Ich habe eine Frage zu meinem Turbo Delphi (was ja im Prinzip ein BDS 2006 ist):
Ich habe eine Basisklasse, die recht viele abstrakte Methoden bereitstellt, welche die Kinder dann überschreiben müssen.

Wie kann ich denn von der Basisklasse eine neue Klasse ableiten ohne dass ich das ganze Grundgerüst per Hand tippen muss? Geht das in der Delphi IDE ?

Danke,
Matze


MSCH - Sa 23.08.08 20:30

vieleicht so?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
type 
  irgenteineKlasse = Class(<...>)
    procedure do Something; abstract;
    ...
  end;

  MeineNeueKlasse = Class(irgenteineKlasse)
    ...
    procedure do Something; 
   
  end;


du musst lediglich die Deklaration übernehmen und implementieren.

oder verstehe ich deine Frage falsch?

grz
Msch


jaenicke - Sa 23.08.08 20:31

Das ist ihm schon klar, es ging ihm darum dass das automatisch passiert eben ohne das Kopieren der abstrakten Routinen.
Ich kenne da keine entsprechende Funktion.


matze - Sa 23.08.08 22:37

user profile iconjaenicke hat folgendes geschrieben:
Das ist ihm schon klar, es ging ihm darum dass das automatisch passiert eben ohne das Kopieren der abstrakten Routinen.

Der Mann hat mich verstanden :)


Kha - Sa 23.08.08 23:26

Für die gesamte Klasse ohne irgendwelche 3rd-Party-Tools: Geht wohl nicht.

Wenn du Intellisense im Interface aufrufst, kannst du wenigstens Methode-für-Methode die korrekten Deklarationen erstellen lassen. Am Schluss noch Strg + Shift + C, um die Rümpfe zu erstellen.


jaenicke - Sa 23.08.08 23:34

Ich habe mir mal den Code eines Plugins für die Delphi IDE angeschaut, das ich mal geschrieben habe. Das Problem ist, dass die Funktionalität von Delphis ToolsAPI nicht nutzbar ist, weil in Turbo Delphi ja nichts installiert werden kann. Dennnoch denke ich, dass ich da was hinbekomme, nicht so komfortabel integriert wie mit der ToolsAPI und in Delphi selbst, aber fast.

Wie ich mir das denke: Das Programm läuft in der Tray, Hotkey drücken, Name der Elternklasse aus einer Liste auswählen, Name der neuen Kindklasse eingeben, das Programm fügt den Quelltext der neuen Klasse ein, fertig.

Das interessiert mich jetzt :mrgreen:. *Delphi startet*

// EDIT: Warum funktioniert WM_GETTEXT dort nicht? O.o
Der Rest sollte soweit gehen, aber ich komme nicht direkt an den Text heran... Naja, mal schauen.


matze - So 24.08.08 09:38

Oh, das solle ich vielleicht erwähnen: Ich hab die Prof Variante von den Turbos. Also kann man da alles machen was man auch im BDS 06 machen kann. Ok bis auf die anderen Personalities wie C#...

In dem Sinne wäre ein IDE Experte wohl doch die bessere wahl, oder ?


Hidden - So 24.08.08 10:23

Hi,

Also bei meinem Turbo Delphi kann ich theoretisch xml-Templates Schreiben. Damit müsste das doch eigentlich gehen :?:

mfG,


matze - So 24.08.08 10:33

Ich glaube nicht. Das geht vielleicht für das allgemeine Grundgerüst einer Klasse aber nicht für ein spezielles einer abgeleiteten Klasse...


Hidden - So 24.08.08 10:44

Ich kenne mich jetzt mit xml nicht aus, aber nach reiner String-Verarbeitung müsste ja nur beim Tippen einer Klasse die Klasse in Klammern gesucht werden. Dort dann alle Methoden, hinter denen abstract steht kopieren..

Geht das mit xml nicht?


jaenicke - Mo 25.08.08 03:46

user profile iconmatze hat folgendes geschrieben:
Oh, das solle ich vielleicht erwähnen: Ich hab die Prof Variante von den Turbos. Also kann man da alles machen was man auch im BDS 06 machen kann. Ok bis auf die anderen Personalities wie C#...

In dem Sinne wäre ein IDE Experte wohl doch die bessere wahl, oder ?
Ja, sicher und ich glaube den gibts auch schon, ich werde mal schauen, auf jeden Fall funktioniert es bei mir, dass ich aus einer Unit die Klassen erkenne und nach der Auswahl dann das Skelett einer neuen Klasse erstelle. Mit Hilfe der ToolsAPI sollte das dann recht einfach sein das auch direkt im Editorfenster zu benutzen. Ich verreise Ende nächster Woche, werde aber sehen, dass ich dazu noch etwas Zeit finde vorher.


matze - Mo 25.08.08 10:01

Man darf also gespannt sein :-)


Martin1966 - Mo 25.08.08 10:14

user profile iconKha hat folgendes geschrieben:
Wenn du Intellisense im Interface aufrufst, kannst du wenigstens Methode-für-Methode die korrekten Deklarationen erstellen lassen.

Wenn mich nicht alles täuscht kann man sogar mehrere Methoden auswählen (mit UMSCH und/oder STRG).

Lg, Martin


Reinhard Kern - Mo 25.08.08 15:07
Titel: Re: Klasse ableiten -> Editor soll Grundgerüst stellen
user profile iconmatze hat folgendes geschrieben:
Hallo.

Ich habe eine Basisklasse, die recht viele abstrakte Methoden bereitstellt, welche die Kinder dann überschreiben müssen.


Hallo,

wenn du den Kids Schreibarbeit ersparen willst, füg doch einfach einen Kommentarblock ein mit den Klassendefinitionen aller abstrakt definierten Klassen - Copy & Paste beherrschen die doch im Schlaf.

Ok, ist vielleicht kein glänzendes Beispiel für reine OO-Lehre.

Gruss Reinhard


matze - Mo 25.08.08 18:00

:lol: Ich glaube du hast mich da ein bisschen falsch verstanden.. OK ich habe mich da auch missverständlich ausgedrückt.
Gemeint sind die Kind-Klasse und nicht irgendwelche Kinder :lol:


Hidden - Mo 25.08.08 19:26

user profile iconmatze hat folgendes geschrieben:
Gemeint sind die Kind-Klasse und nicht irgendwelche Kinder :lol:

*Sich weg schmeißt* Ich hatte mir schon gemerkt: 'Ah, Lehrer ist der' :lol:


MSCH - Mo 25.08.08 20:03

Kurze Frage; warum schreibst du abstrakte Funktionen in den Classes?
Wäre es nicht günstiger ein oder mehrere Interfaces zu deklarieren und deine Child-Classes (nicht das es wieder zu missverständnissen führt :-) ) sich davon ableiten bzw. diese implementieren?

Das Interface deklarierst du doch nur einmal und deine Klassen erben nicht nur den Vorfahr sondern implementieren
auch die Interfacefunktionen.

:-)msch


matze - Mo 25.08.08 21:57

Das läuft ja auf das gleiche Problem hinaus.
Wenn ich eine neue Klasse habe, die von einem Interface die Funktionen erbt, dann muss diese Funktionen im Interface-Abschnitt per Hand eintippen. Und das können, je nach Modell, recht viele sein.
Und genau das will ich nicht. Ich möchte eine Funktion haben, dass wenn ich eine Klasse erstelle die irgendwas erbt (sei es von einer Super-Klasse oder von einem Interface) diese Funktionsrümpfe automatisch in den Quelltext geschrieben werden.

Zum Verständnis:
Ich habe folgende Super-Klasse: (könnte auch ein Interface sein)

Delphi-Quelltext
1:
2:
3:
4:
5:
type
  TBasis = class(TObject)
  published
    procedure tuwas(i: integer); virtualabstract;
  end;


Dann möchte ich irgendwo klicken und sagen: "Leite mir von TBasis eine neue Klasse TExtendedBasis ab" und das Programm erstellt mir das:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
type
  TExtendedBasis = class(TBasis)
  published
    procedure tuwas(i: integer); override;
  end;

{...}

implementation

procedure TExtendedBasis.tuwas(i: integer);
begin
   inherited;
end;


jaenicke - Mi 10.09.08 15:36

So, mal eine kurze Zwischenmeldung ;-).
Ich bin mittlerweile wieder da, hatte auch etwas Zeit, und habe mich da drangesetzt.
Ergebnis ist, dass es soweit zu funktionieren scheint, es wird der Quelltext geparst (mit einem Open Source Parser) und dann von mir so zusammengesetzt, dass das Gerüst steht. Im Moment gibt es bei manchen Dateien noch Probleme, das habe ich aber bald soweit.

Was ich dann noch machen möchte ist, dass man standardmäßig die Liste der Klassen der aktuellen Datei im Editor bekommt (funktioniert), dann aber auch eine andere offene Unit und eine dortige Klasse auswählen kann und auch eine bestimmte offene Unit als Ziel angeben kann.

Das dauert noch ein paar Tage, je nachdem wieviel Zeit ich habe, aber es sieht soweit gut aus ;-).

Was ich danach dann noch überlege ist, ob ich es auch hinbekomme die Units aus den uses-Klauseln mit zu benutzen. Die müssen ja für das Projekt auch verfügbar sein (ich müsste die also auch nutzen können). Aber das kommt dann, wenn der Rest fertig ist.


matze - Do 11.09.08 09:04

Wow. Das hört sich ja schon gut an. Man darf also gespannt bleiben...


jaenicke - Do 25.09.08 10:36

Also, es sollte soweit alles funktionieren, ich werde Samstag oder Sonntag dann das entsprechende Package posten, im Moment fehlt noch eine kleine Oberfläche und die Speicherung der Einstellungen.

Zunächst kannst du wenn du möchtest schon mal den Parser testen, er sollte aus der Deklaration alle Klassen und die entsprechenden Methoden suchen und anzeigen. Der auf der rechten Seite angezeigte Quelltext wird dabei selbst zusammengebaut, d.h. es wurde vorher alles (objektorientiert) gespeichert.
Wenn die Klasse Interfaces implementiert, sollten darin enthaltene Methoden ebenfalls aufgeführt sein (das funktioniert im Beispiel nur, wenn das Interface in der selben Unit implementiert ist, sollte aber im Experten dann auch gehen, wenn es in anderen Units deklariert ist).

Im Experten sollte es auch dann gehen, wenn irgendwo erreichbar der Quelltext der Unit liegt, wobei ich da noch überlege zusätzliche Funktionen hinzuzufügen, die es erlauben die Units auch dann zu finden, wenn sie nicht im Suchpfad liegen (indem der Benutzer vorher eigene Suchpfade / Unitlisten angibt oder eine Verzeichnisstruktur nach Units durchsuchen lässt, mal schauen was ich da mache).

Ach ja: Fehler beim Parsen werden derzeit noch nicht behandelt, das kommt erst bei der Integration in den Experten dazu.

// EDIT:
Fehler: Records mit Feldern mit direkter Angabe einer Methode als Typ werden nicht korrekt geparst. --> Exception
Also sowas wie

Delphi-Quelltext
1:
2:
TXy = record
  xy: function...

Fehler: Klassenfunktionen werden nicht erkannt.

// EDIT: Parsertest.exe wieder entfernt, im nächsten Beitrag von mir gibts die neue Version ;-).


matze - Fr 26.09.08 19:47

Ich habe mir dein Testprogramm grade mal runtergeladen. Mit dem Quelltexten, für die ich so eine Funktionalität hätte brauchen können, funktioniert es einwandfrei. Die Methoden werden korrekt erkannt und ausgegeben :-)
Cool!


jaenicke - So 28.09.08 16:42

Nachdem ich heute festgestellt habe, dass sowohl Konstruktoren als auch Destruktoren als leere Prozeduren ankommen, dazu bereits die beiden bereits von mir angesprochenen Probleme, und sich Delphi-eigene Quelltextdateien gar nicht parsen lassen (Exceptions), habe ich mich da noch einmal drangesetzt, mit dem Ergebnis, dass jetzt in Tests mit ca. 100 teilweise recht komplexen Dateien keine Probleme mehr aufgetreten sind.

Der Experte selbst kommt daher erst morgen dran, im Anhang befindet sich der korrigierte Parser.


matze - Mo 03.11.08 14:26

Gibts denn mittlerweile schon Fortschritte?


jaenicke - Di 04.11.08 19:40

Ja, gibt es, ich habe leider kaum Zeit gehabt, deshalb ist es nicht wirklich fertig.
Das Problem ist, dass ich irgendwo vermutlich ein Speicherleck habe und nicht die Zeit hatte mir das genauer anzuschauen.
Wegen des Fehlers fehlt auch noch die Auswahl der Methoden, da ich erstmal mich darum kümmern muss.

Ich kann ja die aktuelle Arbeitsversion mal hochladen. Um keinen Quelltext zu verunstalten ist die Funktion zur tatsächlichen Änderung der Zielunit nicht dabei, es wird nur eine Vorschau des generierten Quelltexts erzeugt (aus der man natürlich auch kopieren kann).

Es sollte die Auswahl der Quellunit, der Quellklasse und der Zielunit funktionieren, auch die Vorschau sollte korrekt erzeugt werden. Mit dem Eintrag im Hilfemenü kommt man auch zur Konfiguration, in der man das Menü, in dem der Eintrag erscheint, sowie dessen Shortcut festlegen kann. Dies wird unter "HKEY_CURRENT_USER\Software\Borland\BDS\4.0\SJDelphiCodeAssist" in der Registry gespeichert. Fehlen tut an der Stelle die Anpassung für verschiedene Delphiversionen.

Der gesamte Quelltext steht unter der MPL, inklusive des verwendeten Parsers (dieser ist leicht verändert, das fehlt noch in der Copyright Angabe!!) und eines Teils von SynEdit. Dies ist eine Alpha Version, deshalb muss der Lizenzteil und die Dokumentation noch überarbeitet bzw. erstellt werden.

Bekannte Bugs:

Probleme / ungeprüft / nicht implementiert:

Das größte Problem ist, dass die ganze Realisierung nicht so ist wie ich mir das vorstelle. Weil ich die Möglichkeiten der ToolsAPI nicht so gut überblicke bisher bzw. es Fehler gab wird im Moment ständig alles neu erstellt und wieder aus dem Speicher entfernt, auch die Weitergabe von Daten etc. ist suboptimal, da so bei der Verwendung der falschen Events (FormCreate statt FormShow...) Fehler auftreten.
Das muss ich entweder noch korrekt dokumentieren oder anders lösen.