Domino 9 und frühere Versionen > ND6: Entwicklung
Lotus Script + Objektorientierte Programmierung + Methodenaufruf der Superklasse
(1/1)
Skorpi:
Hallo Leutz,
folgendes Szenario:
Mal angenommen es existieren zwei Klassen Person und Mitarbeiter. Wobei die Mitarbeiter-Klasse von der Personen-Klasse erbt. Nun habe ich folgendes Problem. Wenn ich bei dem Mitarbeiter-Objekt die Methode save aufrufe, wird leider nicht die gleichnamige Methode der Superklasse (in diesem Fall Person) aufgerufen. Bei der Methode new hingegen funktioniert der automatische Aufruf der Methode in der Superklasse.
Hat jemand eine Lösung für das Problem.
Die Klassen:
--- Code: ---Public Class Person
Private doc As NotesDocument
Private strVorname As String
Private strNachname As String
Sub new(doc As NotesDocument)
If Not doc Is Nothing Then
Set Me.doc = doc
Me.strVorname = doc.GetItemValue("vorname")(0)
Me.strNachname = doc.GetItemValue("nachname")(0)
End If
End Sub
Property Get Vorname As String
Vorname = Me.strVorname
End Property
Property Set Vorname As String
Me.strVorname = Vorname
End Property
Property Get Nachname As String
Nachname = Me.strNachname
End Property
Property Set Nachname As String
Me.strNachname = Nachname
End Property
Sub save
Call Me.doc.ReplaceItemValue("vorname", Me.Vorname)
Call Me.doc.ReplaceItemValue("nachname", Me.Nachname)
Call Me.doc.save(True,False,False)
End Sub
End Class
Public Class Mitarbeiter As Person
Private intPersonalnummer As Integer
Sub new(doc As NotesDocument)
If Not doc Is Nothing Then
Me.intPersonalnummer = Cint(doc.GetItemValue("personalnummer")(0))
End If
End Sub
Property Get Personalnummer As Integer
Personalnummer = Me.intPersonalnummer
End Property
Property Set Personalnummer As Integer
Me.intPersonalnummer = Personalnummer
End Property
Sub save
Call Me.doc.ReplaceItemValue("personalnummer", Me.Personalnummer)
Call Me.doc.save(True,False,False)
End Sub
End Class
--- Ende Code ---
Zum Testen habe ich den folgenden Agenten angelegt:
--- Code: ---Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim docMitarbeiter As NotesDocument
Set db = session.CurrentDatabase
Set docMitarbeiter = New NotesDocument(db)
docMitarbeiter.Form = "Mitarbeiter"
Call docMitarbeiter.ReplaceItemValue("vorname", "Max")
Call docMitarbeiter.ReplaceItemValue("nachname", "Mustermann")
Call docMitarbeiter.ReplaceItemValue("personalnummer", 1234)
Call docMitarbeiter.Save(True,False,False)
Dim ma As New Mitarbeiter(docMitarbeiter)
Print ma.Vorname 'Ausgabe: Max
Print ma.Nachname 'Ausgabe: Mustermann
Print ma.Personalnummer 'Ausgabe: 1234
ma.Vorname = "Maxi"
ma.Nachname = "Musterfrau"
ma.Personalnummer = 4321
Call ma.Save
Set ma = New Mitarbeiter(docMitarbeiter)
Print ma.Vorname 'Ausgabe: Max <------ kein Maxi
Print ma.Nachname 'Ausgabe: Mustermann <------ kein Musterfrau
Print ma.Personalnummer 'Ausgabe: 4321
End Sub
--- Ende Code ---
Glombi:
Aus der Hilfe:
Accessing base-class properties and methods
A derived class can call a property or method in a base class, even if that method was overridden in the derived class. You use two dots (dotdot notation) to access a base class’s overridden method. Dotdot notation is valid only in class scope (within a Class statement).
The syntax is:
baseClassName..propertyName (parameters)
or
baseClassName..methodName (parameters)
For example, you can override a method just to add additional processing. You would call the base class’s method and then do the extra processing in the derived class method.
Andreas
flaite:
Das ist in Java, VB.NET, C# und C++ nicht anders.
Die Idee von overwriding ist ja gerade, dass genau die Methode des Runtime-Types aufgerufen wird.
In Java kann man Methoden von Super-Klassen mit super.<methodenName> aufrufen.
Die Konstruktoren werden demgegenüber auch in Java, VB.NET, C# und vermutlich auch C++ der Reihe nach aufgerufen. Und zwar angefangen beim Konstruktor der obersten Super-Klasse. Das ist konzeptionell korrekt, weil ja Mitarbeiter is a Person und dann muss eben auch der Konstruktor von Person initialisiert werden, wenn du einen Mitarbeiter willst. Mit den Methoden ist das aber was anderes. Meist will man da gar nicht, dass die Methoden der Super-Klasse aufgerufen werden. Konstruktoren sind eben was anderes als Methoden.
Objektorientiertes JavaScript kennt übrigens überhaupt keine Vererbung, wobei es da Tricks gibt, das zu simmulieren, aber das nur am Rande.
Und nun wirds völlig Offtopic und bezieh das jetzt bitte nicht auf dich:
Ich glaub, dass das von Bob Balaban oder einem anderen Entwickler der Sprache LotusScript erstellten OO-Features von LotusScript falsch eingesetzt werden. Irgendwie fehlt da ein bischen eine Unterscheidung zwischen Domain Driven Design (das heisst ein komplettes OO-Modell zu erstellen) und einfach die netten Features des Schlüsselwortes "class" zu nutzen.
Ich nutz z.B. eine Menge das Konstrukt class, seh das aber oft nicht als Objektmodell sondern als eine Art Skript-Library, die einen Satz von Funktionen und Variablen hat, die für die Objekte der Klasse global sind, aber ausserhalb nicht gesehen werden können.
Der Zweck ist nicht die "reale Welt abzubilden", weil das nicht geht. Es geht vielmehr darum Duplizierung von Code zu vermeiden.
Ich hab hier z.B. 4 Buttons in einer per store-form-in-Document an eine Usermail geschickt werden. Der User erzeugt darüber eine Mail, die an eine Mail-In-DB geht. Es werden spezielle Felder in der Mail gesetzt, dafür Werte aus der einkommenden Mail ausgelesen, in manchen Fällen gibt der User was in den Prompt-Boxen ein. In 2 Fällen wird die Mail direkt aus dem Button versendet, in anderen Fällen öffnet sich ein neues UIDoc per Uiws.editDocument mit ein paar Backend-Feldern, die im Code des Buttons da reingesetzt wurden. Und gerade für solche typischen Domino-Fälle kann man imho mit einer Klasse viel einfacheren und übersichtlicheren Code schreiben.
Anstatt also das Thema OO mit dem Anspruch zu begegnen, nun die Welt zu modellieren, könnte man sich vielleicht auch überlegen, einfach mal für typische Aufgaben eine Klasse zu schreiben. Mit dem bescheidenen Ziel übersichtlichen Code zu schreiben, in dem NICHTS dupliziert ist. Anfänger werden da Fehler machen. Aber imho lohnt es sich. Und wenn man da ein bischen Sicherheit gewinnt, die Nachteile kennenlernt, etc.. Dann kann man versuchen Domains in Klassen zu modellieren. Das ist aber ziemlich schwierig.
Das mehr als eigene späte Erkenntnis und Anregung und nicht als rant.
Gruß Axel
Skorpi:
Guten morgen,
erstmal vielen Dank für die schnelle und sehr gute Hilfe. Irgendwie schäm ich mich nur ein bisschen, dass ich die Antwort (dotdot notation) nicht selbst in der Hilfe gefunden habe. Mehr zum Thema Klassen und LotusScript befindet sich in der Hilfe unter dem Inhaltspunkt: LotusScript Language -> User-Defined Data Types and Classes
Also die Lösung mit der dotdot notation sieht dann im obigen Beispiel wie folgt aus:
--- Code: ---Public Class Mitarbeiter As Person
...
Sub save
Call Me.doc.ReplaceItemValue("personalnummer", Me.Personalnummer)
Person..save ' --> ruft die Methode der Save der Klasse Person auf
End Sub
...
End Class
--- Ende Code ---
Das ganze funktioniert genau so wie ich mir das vorgestellt habe und wie ich es aus meiner Zeit als Java-Entwickler kenne.
@Axel
Da gebe ich dir Recht, es ist natürlich nicht sinnvoll die reale Welt bis in das kleinste Detail abzubilden. Vielmehr lassen sich bestimmte Dinge (ob das nun Objekte der realen Welt oder eine Zusammenfassung von Funktionen sind, ist egal) sinnvoll in Klassen zusammenfassen. Die durch den richtigen Einsatz der objektorientierten Programmierung entstehenden Klassen-Hierarchien (Vererbung) und -Beziehungen unterstützen den Entwickler bei der Erstellung komplexer Anwendungen.
flaite:
@Skorpi,
I have just discovered...
für mich gibt es 2 Arten des Einsatzes des Schlüsselwortes "class" in LotusScript:
1. Der Versuch die gesamte business Domain als Objekte abzubilden.
2. Bestimmte, eng fokussierte technische Aufgabenstellungen wie z.B. das Auslesen von HTTP-Parametern in Lotus-Web Agenten, das Handling von Business Logik, die an Button Clicks in einer Maske gebunden ist, etc.
Das zweite ist ein weniger ambitionierter Hybridansatz. Die Datenstrukturen und Algorithmen müssen dabei nicht Objekte sein. Nur für bestimmte, eng fokussierte Aufgaben werden Klassen geschrieben.
Beide Ansätze das class feature in LotusScript zu nutzen sind sehr unterschiedlich.
Ich glaube nicht, dass Klassen in komplexeren Anwendungen wirklich helfen. Nicht zuletzt deshalb, weil in Lotus Notes Anwendungen die den Business Case bedienenden Datenstrukturen schon in DOKUMENTEN gespeichert sind. Und Dokumente sind etwas freaking anderes als Objekte im OO-Verständnis. Will man die gesamte business Domain als Objekte darstellen, müsste man die Dokumente auf die Objekte mappen und das schafft eine eigene Komplexität.
Viel effektiver erscheint mir da schon Ansatz 2. Ein Entwickler kennt sich in einer technischen Domäne sehr gut aus. Etwa die Verarbeitung von HTTP-Parametern in Web-Agenten. Der kann die Logik in Skriptbibliotheken schreiben oder dafür Klassen verwenden. Und Klassen bringen da Vorteile, völlig losgelöst von jeder Objekt Orientierten Analyse, die auf die business domain abzielt.
Nachdem ich über einen langen Zeitraum fast nur noch Java programmiert habe und jetzt wieder 1 LotusScript und 1 LotusScript/JavaScript Projekt betreue sind mir diese Überlegungen gekommen. Ich benutze zwar viel CLASS, mach aber keine objekt orientiert Analyse im Sinne von etwa Domain Driven Design.
Im Codestore blog hat der Autor auch "class" in diesem enge-technische-Domain-Sinne für sich entdeckt (z.B. http://www.codestore.net/store.nsf/unid/BLOG-20070815?OpenDocument oder http://www.codestore.net/store.nsf/unid/BLOG-20070814/
Ich hijacke hier natürlich ziemlich diesen Thread.
Vom Tooling des Domino Designer her werden user defined classes kaum unterstützt. Mit dem freien Teamstudio Script browser (try google) gibts aber inzwischen zumindest ein funktionierendes "Inspektionstool", dh. es listet automatisch die Membervariablen und Methoden von user defined classes auf. Theoretisch kann man mit ANTLR (google) selbst einen LotusScript Parser, Lexer, etc schreiben, mit dessen output man dann eigenes Tooling für LotusScript und sogar Formelsprache Designelemente in einer Lotus Notes Datenbank schreiben kann. Das Eclipse basierte openSource Projekt "Domiclipse" hat genau damit angefangen.
Gruß Axel
Gruß Axel
Navigation
[0] Themen-Index
Zur normalen Ansicht wechseln