CONSTRUCTOR & Co. [Sammeln & Seltenes]

Die Objektorientierung mit ABAP®: Vererbung, Dynamische Programmierung, GUI Controls (u.a. ALV im OO).
43 Beiträge • Vorherige Seite 2 von 3 (current) Nächste
43 Beiträge Vorherige Seite 2 von 3 (current) Nächste

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von erp-bt (Specialist / 163 / 4 / 21 ) »
a-dead-trousers hat geschrieben:Ich bin ne faule Sau und deher hatte ich nicht die Zeit alle Postings zu lesen, aber ein Prolem über das ich immer wieder stolpere ist, dass man CONSTRUCTOR-Methoden und daraus aufgerufene Methoden (in ABAP) NICHT so überladen kann wie erwartet. Deswegen baue ich in meinen ganzen Frameworks z,B. eine INITIALIZE Methode ein die grundsätzlich den Constructor ablöst und wie aus anderen Programmiersprachen erwartet überladen werden kann.
Das Problem ist, dass ABAP im Constructor (und nur da) die Vererbung ignoriert. Das bedeutet, dass bei einer Methode die im Constructor einer untergeordneten Klasse aufgerufen wird, nicht die überladene Methode einer übergeordneten Klasse aufgerufen wird sondern nur die aktuelle Methode der untergeordneten Klasse.
Grundsätzlich kein Drama, wenn man weiß, dass sich ABAP so verhällt, aber dennoch ein Problem für jemanden, der aus einer anderen Programmierumgebung kommt. Man kann dies mit Framworks umgehen die z.B. eine INITIALZE-Methode verwenden die zwingend nach dem CONSTRUCTOR aufgerufen werden muss und somit die spezielle ABAP-Vorgabe der Constructor-Aufruf-Hierarchie umgeht.

Wenn das jemand anderes hier bereits eingebracht hat, möchte ich mich enschuldien, aber ich wollte diesen Punkt weder unter den Tisch fallen gelassen noch zu sehr hervorgehoben wissen.

lg ADT
Hmm, ich habe das zwar noch nie benötigt, aber kannst Du die Methode der übergeordneten Klasse nicht einfach mit "SUPER->" aufrufen?

Generierst Du Dir durch eine separate INITIALIZE-Methode nicht eine Abhängigkeit zur rufenden Klasse oder rufst Du die im Constructor? Würde mich mal interessieren.

Liebe Grüße, Tapio
...entwickelnder Berater...beratender Entwickler

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
black_adept hat geschrieben:
ralf.wenzel hat geschrieben:• Bei mir ändert sich die Methodenschnittstelle nicht, wenn die Definition des Timestamps sich ändert
WAS?
Ich kann das Verhalten der Klasse doch jederzeit ändern. An der Methodenschnittstelle ändert das nichts, die bekommt das Objekt. Was passiert, wenn du z. B. die Zeitzone mit in den Timestamp reinrechnen sollst? Dann brauchst du einen weiteren Parameter, entweder optional oder du änderst alle Aufrufe. Ich baue eine neue Setter-Methode und schreibe damit ein neues Attribut, als Parameter übergebe ich trotzdem mein „altes“ Interface. In agilen Projekten kommt es ständig vor, dass sich sowas ändert.

Deine Ausführungen zeigen genau, was ich sagte: Du betrachtest eines Klasse als ein Programm-Modul. So wie eine Funktionsgruppe, wo man mehrfach benötigtes Coding kapselt. Das ist genau NICHT das Konzept von OO. Denn dieses bindet das Verhalten von Datenobjekten an das Datenobjekt selbst.

Ein Timestamp ist ein komplexer (aus mehreren elementaren Datentypen bestehender) Datentyp mit einem speziellen Verhalten (der Ermittlungslogik für den Timestamp). Somit ist es per Definition ein Objekt. Sobald du Verhalten von Datentyp trennst, musst du basteln, wenn sich etwas ändert. Warum arbeitest du nicht mit Objekten, wenn du OO codierst? Bzw. warum auf halbem Wege stehenbleiben, wenn das Weitergehen Vorteile bringt - nämlich das nicht-erweitern-müssen der Methodenschnittstelle?

Nehmen wir das Verhalten einmal aus der Betrachtung: Übergib eine Struktur statt der Einzelfelder. Auch die kannst du jederzeit ändern, ohne die Methodenschnittstelle ändern zu müssen.
erp-bt hat geschrieben:
black_adept hat geschrieben:
  • Kann man eigentlich sagen, dass die Methode "GET_INSTANCE" eine Factory-Methode für den Singleton-Pattern ist?
Nein, könnten zur Laufzeit ja ganz unterschiedliche Instanzen geholt werden. Je nachdem was man gerade benötigt. GET_INSTANCE ist einfach das delegieren der Instanzerzeugung, kann dann natürlich auch ein Singleton sein.
Zumeist nennt man die Methode beim Singleton GET_INSTANCE, ansonsten CREATE. Darum sind Parameter beim CREATE üblich, beim GET_INSTANCE eher selten.
erp-bt hat geschrieben:
black_adept hat geschrieben:
  • Sollte man bei Verwendung von Factories die Instanzerzeugung der Klasse auf "Private" stellen
[/list]
Sollte so sein. Wenn Du eine separate Factory-Klasse hast, muss diese allerdings dann als "Friend" der eigentlich zu instantiierenden Klasse definiert werden.
Der Zweck einer Factory ist die Entkoppelung, dann sollte man verhindern, dass jemand an der Factory vorbei Objekte erzeugt. Das geht nur so.


Ralf
Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von black_adept (Top Expert / 3943 / 105 / 886 ) »
ralf.wenzel hat geschrieben:
black_adept hat geschrieben:
ralf.wenzel hat geschrieben:• Bei mir ändert sich die Methodenschnittstelle nicht, wenn die Definition des Timestamps sich ändert
WAS?
Ich kann das Verhalten der Klasse doch jederzeit ändern. An der Methodenschnittstelle ändert das nichts, die bekommt das Objekt. Was passiert, wenn du z. B. die Zeitzone mit in den Timestamp reinrechnen sollst? Dann brauchst du einen weiteren Parameter, entweder optional oder du änderst alle Aufrufe. Ich baue eine neue Setter-Methode und schreibe damit ein neues Attribut, als Parameter übergebe ich trotzdem mein „altes“ Interface. In agilen Projekten kommt es ständig vor, dass sich sowas ändert.
Deine Ausführungen zeigen genau, was ich sagte: Du betrachtest eines Klasse als ein Programm-Modul. So wie eine Funktionsgruppe, wo man mehrfach benötigtes Coding kapselt. Das ist genau NICHT das Konzept von OO. Denn dieses bindet das Verhalten von Datenobjekten an das Datenobjekt selbst
Deine Ausführungen zeigen, dass du selbst da Objekte siehst, wo ich einfach nur subtriviale Funktionalitäten sehe. Wenn du der Meinung bist für so was wie das o.a. Zeitstempelbeispiel eine eigene Klasse zu benötigen - es sei dir gegönnt. Bei mir tut es tatsächlich eine Methode ( mit dann von mir aus optionalem Parameter für die Zeitzone oder eine Alternativmethode mit zusätzlich dem Zeitstempel dabei oder ...). Dass sich dann bei mir nicht das Verhalten eines Datenobjekts sondern nur das Verhalten einer Methode ändert macht mich jetzt nicht sonderlich traurig.
Und das Verhalten der Methode ist genau so an ihre Schnittstelle gebunden wie bei dir das Verhalten der Klasse an die vorhandenen Setter-Methoden.
ralf.wenzel hat geschrieben: Du betrachtest eines Klasse als ein Programm-Modul. So wie eine Funktionsgruppe, wo man mehrfach benötigtes Coding kapselt.
Wohl kaum. Aber ich betrachte Methoden häufig als Programm-Modul - und genau davon sprachen wir ursprünglich als du ausführtest, eine in meinen Augen einfach und sinnvoll entworfene Methode in ein anderes Rahmenkonzept zu bringen. Und ich halte in diesem speziellen Fall deine Vorgehensweise tatsächlich für einen Overhead, der für mich keinen Mehrwert in Lesbarkeit oder Wartbarkeit bietet. Mag ja sein, dass so was bei komplexeren Dingen seine Daseinsberechtigung hat - aber nicht hier.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Overhead ist Teil des OO, das ist so. Aber wenn man die OO-Betrachtungsweise durchzieht, ist eben ALLES ein Objekt. Aus Wikipedia:

Ein Objekt ist:
Ein Element, welches Funktionen, Methoden, Prozeduren, einen inneren Zustand, oder mehrere dieser Dinge besitzt.
und:
Die Klasse entspricht in etwa einem komplexen Datentyp wie in der prozeduralen Programmierung, geht aber darüber hinaus: Sie legt nicht nur die Datentypen fest, aus denen die mit Hilfe der Klassen erzeugten Objekte bestehen, sie definiert zudem die Algorithmen, die auf diesen Daten operieren.
Nirgendwo steht „eine Klasse ist ein Teil eines Programms“, weil ein Objekt eben ein eigenständiges Etwas ist, das sich mit prozeduralen Begriffen nicht umfassend erklären lässt.

Man mag kleine Klassen obsolet finden und vermeintlich pragmatischere Wege finden (das ist dann aber prozedurales Programmieren mit Klassen), aber konzeptionell passt das schon. Und zu „keine Vorteile“: Ich kenne viele alte Methoden, denen man das Alter an der Schnittstelle anmerkt: Parameter, die optional sind oder gar als „nicht mehr verwenden“ gekennzeichnet. Sowas sieht aus wie eine Baustelle und ist ebenfalls erklärungsbedürftig.

OO ist das Programmieren mit Objekten bzw. deren Kommunikation über Methodenaufrufe. Und nichts anderes mache ich. Wenn ich das manchmal mache und manchmal nicht, kann ich es gleich lassen. Zumal ich die Vorteile ja genannt habe.


Ralf

Nachtrag: Keines deiner Argumente spricht dagegen, die Felder als Struktur zu übergeben. Auch das sichert die Signatur der Methode ab und fasst semantisch zusammengehörige Daten zusammen. Das Problem ist: Bei optionalen und ggf. sogar obsoleten Parametern muss ich mir immer die Methode ansehen, die den Timestamp erzeugt. Das will ich aber gar nicht wissen, ich will nur einen Timestamp von der Definition, die mein Kollege vor drei Monaten codiert hat. Wie der das macht und ob sich diese Definition agil geändert hat, interessiert mich nen Keks. Mal so als Beispiel.
Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von a-dead-trousers (Top Expert / 4271 / 213 / 1140 ) »
erp-bt hat geschrieben:Hmm, ich habe das zwar noch nie benötigt, aber kannst Du die Methode der übergeordneten Klasse nicht einfach mit "SUPER->" aufrufen?
Generierst Du Dir durch eine separate INITIALIZE-Methode nicht eine Abhängigkeit zur rufenden Klasse oder rufst Du die im Constructor? Würde mich mal interessieren.
Natürlich kannst du mit SUPER-> auf die ursprügliche Implementierung einer redefinierten Methode zugreifen AUßER im Konstruktor.
Gegeben seinen zwei Klassen X und Y. Y erbt von X. in X wird die Methode A definiert und in Y redefiniert. Die Methode A wird im Konstruktor von X aufgerufen. Instanziert man nun ein Objekt vom Typ Y wird die Methode A von X aufgerufen und nicht A von Y obwohl man eigentlich ein Objekt von Y angelegt hat.
Daher bin ich mittlerweile dazu übergegangen kaum noch Sachen im Konstruktor zu programmieren, sondern eigene INITIALIZE-Methoden dafür zu verwenden. Auch, dass man im Konstruktor nicht sofort auf Attribute der Klasse verweisen kann, solange man den SUPER->CONSTRUCTOR nicht aufgerufen hat, kann zu einem Problem führen. Vorallem dann wenn man anfängt auch Zustände in Klassen abzubilden, weil man dann oft mit den Reihenfolgen der Konstruktoren durcheinander kommt. Mit einer eigenen INITIALIZE-Methode kann man von außen dezidiert sagen, "jetzt ist alles notwendige vorhanden, leg los". Außerdem versuche ich die Methodenschnittstellen so schmal wie möglich zu halten. Nichts verwirrt IMHO mehr als wenn eine Methode "dutzende" Eingabeparametern aufweist und man dann noch auf Abhängigkeiten zwischen den Parametern aufpassen muss. Bestes Beispiel ist hier die Angabe von Datum UND Uhrzeit wenn man eigentlich einen Zeitpunkt übergeben möchte. Oft werden dann auch mehrere Datum (mehrzahl von Datum) und Uhrzeiten übergeben, einmal für Gültigkeiten und dann für den eigentlichen Datensatz.

lg ADT

Folgende Benutzer bedankten sich beim Autor a-dead-trousers für den Beitrag:
erp-bt

Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.18
Basis: 7.50

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von black_adept (Top Expert / 3943 / 105 / 886 ) »
a-dead-trousers hat geschrieben:Bestes Beispiel ist hier die Angabe von Datum UND Uhrzeit wenn man eigentlich einen Zeitpunkt übergeben möchte.
In der Theorie hast du ja recht. Aber ich finde das trotzdem korrekt so vorzugehen, dass man Datum und Uhrzeit abfragt. Grund: Wenn ich beides brauche setze ich halt beide Parameter nicht auf optional --> der Aufrufer muss beide mitgeben.
Das Argument, dass man eigentlich einen Zeitpunkt übergeben will ist völlig korrekt - aber SAP hat nun mal 2 Systemfelder für Datum und Uhrzeit bzw. häufig wird das so auf der DB abgelegt und irgendwo muss dann halt umgerechnet werden auf den Zeitstempel. Und ob man das nun innerhalb der Methode macht oder vorher ist eigentlich egal. Aber wenn ich sicher sein will, dass die Umrechnung korrekt erfolgt mache ich es dann halt lieber innerhalb der Methode, weil ich dann weiß, dass es korrekt implementiert ist und sich der Aufrufer weniger Gedanken machen muss.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von black_adept (Top Expert / 3943 / 105 / 886 ) »
a-dead-trousers hat geschrieben:Natürlich kannst du mit SUPER-> auf die ursprügliche Implementierung einer redefinierten Methode zugreifen AUßER im Konstruktor.
Gegeben seinen zwei Klassen X und Y. Y erbt von X. in X wird die Methode A definiert und in Y redefiniert. Die Methode A wird im Konstruktor von X aufgerufen. Instanziert man nun ein Objekt vom Typ Y wird die Methode A von X aufgerufen und nicht A von Y obwohl man eigentlich ein Objekt von Y angelegt hat.
Um das noch mehr herauszustreichen, was a-d-t gerade gepostet hat: Im Konstruktor während er Objekterzeugung wird nicht die redefinierte Methode aufgerufen, nachher schon.

Code: Alles auswählen.

REPORT.
CLASS lcl_x DEFINITION .
  PUBLIC SECTION.
    METHODS: constructor,
      test.
ENDCLASS.

CLASS lcl_y DEFINITION  INHERITING FROM lcl_x.
  PUBLIC SECTION.
    METHODS:
      test REDEFINITION.
ENDCLASS.

CLASS lcl_x IMPLEMENTATION.
  METHOD constructor. test( ). ENDMETHOD.
  METHOD test. WRITE:/'X'. ENDMETHOD.
ENDCLASS.

CLASS lcl_y IMPLEMENTATION.
  METHOD test. WRITE:/ 'Y' COLOR 3. ENDMETHOD.
ENDCLASS.

END-OF-SELECTION.
  NEW lcl_x( )->test( ). ULINE.
  NEW lcl_y( )->test( ).
a-dead-trousers hat geschrieben:Daher bin ich mittlerweile dazu übergegangen kaum noch Sachen im Konstruktor zu programmieren, sondern eigene INITIALIZE-Methoden dafür zu verwenden.
Dann musst du aber unbedingt dafür sorgen, dass alle Aufrufer, die deine Klassen verwenden wollen, verpflichtend die INITIALIZE-Methoden aufrufen bevor sie wirklich loslegen können. Und genau dafür sind dann doch Factory-Methoden gedacht, die genau das machen bzw. die bei privater Instanzerzeugung halt dafür sorgen, dass der Aufrufer sie verwenden muss und nicht einfach so den Konstruktor verwenden.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von ewx (Top Expert / 4784 / 294 / 628 ) »
Hach, das wird ein Spaß, das alles wieder zu ordnen... :)
Es sind tatsächlich ziemlich viele Aspekte, die bei einer recht banalen Basislogik hinein spielen.

Zwischendurch würde ich diesen Artikel von Naimesh noch einwerfen wollen:
http://zevolving.com/2011/02/class_cons ... fore-whom/

Vielen Dank für die tolle Diskussion!
Allerdings sind bisher nur zwei konkrete Beispiele genannt worden.

Ich würde gerne noch mehr davon haben, damit man die allesamt wichtigen und richtigen Aussagen besser einordnen und bewerten kann. Vielleicht sogar persönliche Erfahrungen a la "erst haben wir das so gemacht, weil... Dann gab es diese Anforderung und wir hatten diese und jene Probleme und haben es danach so gemacht: (...)"

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
black_adept hat geschrieben:genau dafür sind dann doch Factory-Methoden gedacht, die genau das machen bzw. die bei privater Instanzerzeugung halt dafür sorgen, dass der Aufrufer sie verwenden muss und nicht einfach so den Konstruktor verwenden.
Ich wollte das einfach nur mal zitieren, um den wichtigsten Satz aus dem Posting mal prominent herauszustellen. Ich halte es für ein triftige Argumentation gegen wahllose (ungesteuerte, öffentliche) Instanziierung.

Allerdings finde ich es im OO-Kontext ganz besonders wichtig, dass wir die Begrifflichkeiten sehr korrekt anwenden. Was du meinst, ist eine Erzeugungsmethode. Eine Fabrikmethode ist ein Spezialfall einer Erzeugungsmethode. Eine Fabrik / Factory ist eine Klasse zur Erzeugung von Objekten.

Beispiele zur Abgrenzung:

Habe ich eine privat instanziierte Klasse, brauche ich eine öffentliche Methode zur Objekterzeugung (Erzeugungsmethode) die , das Singleton ist dafür ein Beispiel. Die Klasse erzeugt Objekte von sich.

Habe ich eine Klasse mit Unterklassen, die über eine abstrakte Methode (nennen wir sie CREATE) verfügt, die von den Unterkassen implementiert wird, spricht man von einer Fabrikmethode. Der Rückgabeparameter ist hierbei vom Typ der Oberklasse, das zurückgegebene Objekt natürlich nicht. Auch hier erzeugt sich die Klasse ihr eigenes Objekt.

Eine Fabrik ist eine eigene Klasse zur Erzeugung (und ggf. Verwaltung) von Objekten. Das macht man dann, wenn man Erzeugung und Verwendung komplett voneinander trennen will. Die Factory (und nur die!) erzeugt Objekte einer anderen Klasse, weshalb eine Freundschaftsbeziehung notwendig wird (die ich ansonsten nicht mag, weil sie die Kapselung durchbricht).

Und dann gibt es noch die Abstrakte Fabrik, die quasi Fabrikinstanzen erzeugt, die Objekte erzeugen ;)


Ralf
Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von a-dead-trousers (Top Expert / 4271 / 213 / 1140 ) »
black_adept hat geschrieben:
a-dead-trousers hat geschrieben:Daher bin ich mittlerweile dazu übergegangen kaum noch Sachen im Konstruktor zu programmieren, sondern eigene INITIALIZE-Methoden dafür zu verwenden.
Dann musst du aber unbedingt dafür sorgen, dass alle Aufrufer, die deine Klassen verwenden wollen, verpflichtend die INITIALIZE-Methoden aufrufen bevor sie wirklich loslegen können. Und genau dafür sind dann doch Factory-Methoden gedacht, die genau das machen bzw. die bei privater Instanzerzeugung halt dafür sorgen, dass der Aufrufer sie verwenden muss und nicht einfach so den Konstruktor verwenden.
Das eine schließt das andere nicht aus. Der Aufrufer kann ja trotzdem "gezwungen" werden die Factory, Factorymethod oder Createmethod (Blick auf Ralf's Cheatsheet) zu verwenden. Intern läuft dann aber alles über die INITIALIZE-Methode(n) der/des beteiligten Objekte(s). Das mach ich meist dann, wenn meine Kollegen meine Klassen verwenden sollen, ihnen die Erzeugung oder bestimmte Abläufe in der Verwendung zu "kompliziert" sind. Damit entstehen in Abstimmung mit den Kollegen halt wieder Aufruferklassen und -methoden mit überdurchschnittlich vielen Parametern aber wenigstens werden darin meine "schönen und schlanken" Methoden/Klassen verwendet. 8)

Etwas Offtopic, aber weil ich mich gerade glaube wieder zu erinnern:
War hier im Forum nicht mal das Thema das statische Methoden im Kernel speziell behandelt werden und somit "länger" im Speicher geladen bleiben (Stichwort: Garbage Collector) auch wenn von der Klasse sonst nichts mehr benötigt wird? Ralf, hast du das nicht mal eingebracht?
Ich frage desshalb, weil ich das bei uns in der Firma schon länger als Argument vorbringe keine statischen Methoden zu verwenden. Auch als Factory, Create oder Class Constructor versuche ich sie daher so gut es geht zu vermeiden.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.18
Basis: 7.50

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von black_adept (Top Expert / 3943 / 105 / 886 ) »
a-dead-trousers hat geschrieben:Etwas Offtopic, aber weil ich mich gerade glaube wieder zu erinnern:
War hier im Forum nicht mal das Thema das statische Methoden im Kernel speziell behandelt werden und somit "länger" im Speicher geladen bleiben (Stichwort: Garbage Collector) auch wenn von der Klasse sonst nichts mehr benötigt wird? Ralf, hast du das nicht mal eingebracht?
Ich frage desshalb, weil ich das bei uns in der Firma schon länger als Argument vorbringe keine statischen Methoden zu verwenden. Auch als Factory, Create oder Class Constructor versuche ich sie daher so gut es geht zu vermeiden.
Moin a-d-t,
In der Theorie gibt es Gründe für statische und nicht-statische Methoden. Ich glaube nicht, dass man dann die aktuelle Implementierung des Kernels mit seiner Behandlung von statischen Methoden als Argument ranziehen sollte, es sei denn die Performance/Speicherverbrauch verhält sich eklatant anders, zumal sich das ja auch von Release zu Release oder vom drunter liegenden OS abhängig anders verhalten kann. Und wie häufig bist du bisher gezwungen worden den Garbage Collector explizit selber zu starten weil dadurch Probleme gelöst wurden?
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Ich vermeide inzwischen alles statische, weil ich zu oft gemerkt habe, dass ich eine der abgeschnittenen Möglichkeiten doch noch brauche. Performance oder Speicher habe ich im OO nie als Problem empfunden, auch nicht bei einer sechsstelligen Zahl von Objekten.


Ralf

Folgende Benutzer bedankten sich beim Autor ralf.wenzel für den Beitrag:
a-dead-trousers

Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von erp-bt (Specialist / 163 / 4 / 21 ) »
a-dead-trousers hat geschrieben:
erp-bt hat geschrieben:Hmm, ich habe das zwar noch nie benötigt, aber kannst Du die Methode der übergeordneten Klasse nicht einfach mit "SUPER->" aufrufen?
Generierst Du Dir durch eine separate INITIALIZE-Methode nicht eine Abhängigkeit zur rufenden Klasse oder rufst Du die im Constructor? Würde mich mal interessieren.
Natürlich kannst du mit SUPER-> auf die ursprügliche Implementierung einer redefinierten Methode zugreifen AUßER im Konstruktor.
Gegeben seinen zwei Klassen X und Y. Y erbt von X. in X wird die Methode A definiert und in Y redefiniert. Die Methode A wird im Konstruktor von X aufgerufen. Instanziert man nun ein Objekt vom Typ Y wird die Methode A von X aufgerufen und nicht A von Y obwohl man eigentlich ein Objekt von Y angelegt hat.
Daher bin ich mittlerweile dazu übergegangen kaum noch Sachen im Konstruktor zu programmieren, sondern eigene INITIALIZE-Methoden dafür zu verwenden. Auch, dass man im Konstruktor nicht sofort auf Attribute der Klasse verweisen kann, solange man den SUPER->CONSTRUCTOR nicht aufgerufen hat, kann zu einem Problem führen. Vorallem dann wenn man anfängt auch Zustände in Klassen abzubilden, weil man dann oft mit den Reihenfolgen der Konstruktoren durcheinander kommt. Mit einer eigenen INITIALIZE-Methode kann man von außen dezidiert sagen, "jetzt ist alles notwendige vorhanden, leg los". Außerdem versuche ich die Methodenschnittstellen so schmal wie möglich zu halten. Nichts verwirrt IMHO mehr als wenn eine Methode "dutzende" Eingabeparametern aufweist und man dann noch auf Abhängigkeiten zwischen den Parametern aufpassen muss. Bestes Beispiel ist hier die Angabe von Datum UND Uhrzeit wenn man eigentlich einen Zeitpunkt übergeben möchte. Oft werden dann auch mehrere Datum (mehrzahl von Datum) und Uhrzeiten übergeben, einmal für Gültigkeiten und dann für den eigentlichen Datensatz.

lg ADT
Ok, danke. Ich persönlich nutze den Constructor im wesentlichen auch "nur" für Constructor-Injection.

Lange Methodensignaturen sind ja ein bekanntes Code-Smell (gibt's da eigentlich eine sinnvolle deutsche Übersetzung für?). Ich nutze ganz gerne Parameter-Objekte (oder Strukturen), obwohl das natürlich nicht das Abhängigkeitsproblem zwischen den Parametern löst. Unter Umständen ist es auch schwieriger nachzuvollziehen, was eine Methode eigentlich macht, war für mich aber bisher kein Problem.

Liebe Grüße, Tapio
...entwickelnder Berater...beratender Entwickler

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
erp-bt hat geschrieben:Lange Methodensignaturen sind ja ein bekanntes Code-Smell (gibt's da eigentlich eine sinnvolle deutsche Übersetzung für?). Ich nutze ganz gerne Parameter-Objekte (oder Strukturen), obwohl das natürlich nicht das Abhängigkeitsproblem zwischen den Parametern löst. Unter Umständen ist es auch schwieriger nachzuvollziehen, was eine Methode eigentlich macht, war für mich aber bisher kein Problem.
Mal abgesehen vo völlig unnützen Fullquote (hast du eine Ahnung, wie aufwendig das Löschen auf einem Smartphone ist?) gebe ich dir weitestgehend recht. Das mit dem Abhängigkeitsproblem stimmt freilich nicht, weil ich ein Interface oder eine Struktur nachträglich ändern kann. Die Methode juckt es nicht, wie viele Felder die Struktur oder wie viele Komponenten ein IF hat.


Ralf
Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~~ Timestamp

Beitrag von ewx (Top Expert / 4784 / 294 / 628 ) »
ralf.wenzel hat geschrieben:So ungefähr stimmt das, was du schreibst. Es sieht natürlich deutlich mehr aus, weil du „bei mir“ zwei Varianten zeigst. In Wahrheit verwende ich kaum mehr Coding als du.
Dann zeig uns doch mal die Wahrheit. ;)
Wie sieht das INTERFACE aus?
ralf.wenzel hat geschrieben: Der Punkt aber ist:
Es sind drei Punkte </goldwaage>
ralf.wenzel hat geschrieben:• Ich fasse die Daten zusammen, die zusammengehören
Beispiel? Gerade wenn im Falle des Timestamps nur DATUM und UHRZEIT notwendig sind, dann sind sie auch so in der Methode zusammengefasst.
ralf.wenzel hat geschrieben:• Bei mir ändert sich die Methodenschnittstelle nicht, wenn die Definition des Timestamps sich ändert
Selbst wenn: Irgendwo hast du immer Anpassungen. Selbst wenn sich die Schnittstelle nicht ändert: Der Timestamp ändert sich ja und dementsprechend muss der Verwender eh angepasst werden.
ralf.wenzel hat geschrieben:• Ich habe einen Verwendungsnachweis auf die Timestamp-Verwendungen
Hast du mit jeder einfachen GET_TIMESTAMP-Methode auch.



Um einen Timestamp zu erzeugen brauche ich immer ein Datum und eine Uhrzeit. Was man als Varianten überlegen könnte, wäre:
* Ich gebe nur eine Uhrzeit mit und möchte implizit das Tagesdatum haben
* Ich gebe gar nichts mit und möchte den Timestamp für die aktuelle Uhrzeit haben.
Erster Ansatz wäre, die beiden Parameter als OPTIONAL zu kennzeichnen und in der Methode abzufragen, welche Parameter gefüllt sind.
Wenn ich das nicht will, weil ich dem Verwender nicht zutraue, die Parameter richtig zu setzen, dann muss ich mehrere Methoden bauen:
* GET_TS_FOR_DATE_AND_TIME
* GET_TS_FOR_CURRENT_DATE
* GET_TIMESTAMP
Aber auch hier verbergen sich "Gefahren", denn ich habe nun für eine eigentlich recht einfache Aufgabe drei Methoden. Wäre erstmal nicht schlimm. Aber sobald noch andere Methoden dazu kommen, "verschwimmen" diese drei zusammengehörenden Methoden in der Masse der anderen Methoden. Ich muss also wieder ziemlich genau wissen, wie ich was benutzen muss. Nur komplizierter.

Was ich in solchen Situationen ausprobiert habe ist, dass ich funktional programmiert habe:

Code: Alles auswählen.

p_ts = NEW my_timestamp( )->date( p_date )->time( p_time )->get( ).
Ist aber auch nicht schöner oder besser, sondern im Gegenteil nur komplizierter...

Code: Alles auswählen.

PARAMETERS p_date TYPE d.
PARAMETERS p_time TYPE t.
PARAMETERS p_ts TYPE timestamp MODIF ID dis.

CLASS my_timestamp DEFINITION.
  PUBLIC SECTION.
    METHODS date IMPORTING date TYPE d RETURNING VALUE(obj) TYPE REF TO my_timestamp.
    METHODS time IMPORTING time TYPE t RETURNING VALUE(obj) TYPE REF TO my_timestamp.
    METHODS get RETURNING VALUE(ts) TYPE timestamp.
  PRIVATE SECTION.
    DATA mv_date TYPE d.
    DATA mv_time TYPE t.
ENDCLASS.

CLASS my_timestamp IMPLEMENTATION.
  METHOD date.
    mv_date = date.
    obj = me.
  ENDMETHOD.
  METHOD time.
    mv_time = time.
    obj = me.
  ENDMETHOD.
  METHOD get.
    IF mv_date IS INITIAL.
      mv_date = sy-datum.
    ENDIF.
    IF mv_time IS INITIAL.
      mv_time = sy-uzeit.
    ENDIF.
    ts = |{ mv_date }{ mv_time }|.
  ENDMETHOD.
ENDCLASS.

AT SELECTION-SCREEN.
  p_ts = NEW my_timestamp( )->date( p_date )->time( p_time )->get( ).

AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN.
    IF screen-group1 = 'DIS'.
      screen-input = '0'.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.

Vergleichbare Themen

1
Antw.
4292
Views
Haste mal nen Constructor
von DeZone2 » 01.12.2005 15:19 • Verfasst in ABAP Objects®
0
Antw.
4302
Views
Exception Class/Parameter für Constructor
von Thomas R. » 26.04.2013 20:45 • Verfasst in Tips + Tricks & FAQs
4
Antw.
986
Views
Fehler: Constructor wurde nicht definiert.
von sapnup » 02.04.2019 12:07 • Verfasst in ABAP® für Anfänger

Aktuelle Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Tagen von Lucyalison 1 / 64
Interne Tabelle
vor 5 Tagen von black_adept 2 / 133
MaLo-Checker in ABAP
vor einer Woche von A6272 6 / 255

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.

Aktuelle Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Tagen von Lucyalison 1 / 64
Interne Tabelle
vor 5 Tagen von black_adept 2 / 133
MaLo-Checker in ABAP
vor einer Woche von A6272 6 / 255

Unbeantwortete Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Tagen von Lucyalison 1 / 64
Group Items auf einer Filterbar
vor einer Woche von Bright4.5 1 / 107
tRFC Transaktionen SM58
vor 4 Wochen von A6272 1 / 140